我正在 Unity 中创建游戏,我需要跨脚本(或类)访问变量的帮助。我有一个在生成的空对象上运行的脚本,我的
Start()
函数如下所示:
Moneymanager moneymanager = GetComponent<Moneymanager>();
moneymanager.addMoney();
Invoke("despawn", 10f);
我只需要当物体产生时,它会增加玩家的金钱数量。在画布脚本中,在
Update()
函数中,我有这个:
moneyText.text = "$ " + playerMoney.ToString();
当我运行它时,钱并没有增加。我不知道为什么:(.
我尝试了多种访问不同类的变量的类型:
Moneymanager moneymanager;
Moneymanager moneymanager = new Moneymanager();
Moneymanager moneymanager = GetComponent<Moneymanager>();
但是我没有开始工作。
我只需要当对象产生时
因此
Moneymanager
组件未附加到您生成的金钱对象!
Component.GetComponent
转发到 gameObject.GetComponent
并正在寻找您的 Moneymanager
组件 在您刚生成的组件所附加的同一个 GameObject 上!
现在 - 假设只有一个
Moneymanager
实例 - 最简单(也是懒惰)的修复方法是切换到例如FindAnyObjectByType
检索 Type 类型的任何活动加载对象。
FindObjectOfType
的新变体,速度更快
或者你学习并寻求正确的编程模式 - 不,我此时指的不是单例模式;这可能也是一种选择——又是一个懒惰且颇具争议的选择;)
相反,场景中的某些东西正在生成这些新实例。
这个东西位于场景中,可以很好地“知道”(参考)您在同一场景中的
Moneymanager
。
所以
首先,为什么你的新生成的对象需要向管理器添加资金,而不是生成它们的东西?
或者 - 如果上述确实没有选择(例如,如果玩家与生成的物品交互,您只添加金钱) - 您将回调或
Moneymanager
引用注入到生成的对象中。
所以例如
public class YourSpawnedThing : MonoBehaviour
{
private Moneymanager _moneymanager;
public void Initilaize(Moneymanager moneymanager)
{
_moneymanager = moneymanager;
}
}
然后在你生成它的那一刻
[SerializeField] YourSpawnedThing prefab;
[SerializeField] Moneymanager referenceToMoneyManager;
...
var spawnedThing = Instatiate(prefab);
spawnedThing.Initilaize(referenceToMoneyManager);
这基本上是一个依赖注入模式 - 只是不使用许多可用的“神奇”依赖注入库之一。
旁注:帆布相当昂贵。如果您每帧都更改文本,那么每一帧还必须重新布局并再次渲染整个画布!
而不是使用
Update
,您应该只在值实际更改时修改文本。
您可以为此使用属性:
/// <summary>
/// Backing field for <see cref="playerMoney"/>
/// </summary>
private int _playerMoney;
public int playerMoney
{
get => _playerMoney;
set
{
_playerMoney = value;
moneyText.text = "$ " + playerMoney.ToString();
}
}
这样,每当您为
playerMoney
分配值时,它都会自动保持 moneyText
同步。