我在Unity 3D的基于组件的设计模型上遇到了一些麻烦。
这是一个演示我的问题的例子:
class MyComponent : MonoBehaviour
{
MyType entity;
void Start()
{
entity = (MyType)FindObjectsOfType(typeof(MyType)).First();
}
void MyMethod()
{
var x = entity.SomeProperty; // <= NullReference exception
}
}
// ....
var clone = (GameObject)Instantiate(original);
clone.GetComponent<MyComponent>().MyMethod();
有时,并非总是如此,MyMethod
在Start
之前执行,所以我最终要做的就是将我在Start
中通常拥有的所有初始化移到MyMethod
一个丑陋的解决方法:
void Start() { }
void MyMethod()
{
entity = (MyType)FindObjectsOfType(typeof(MyType)).First();
var x = entity.SomeProperty; // <= now it's fine.
}
我的问题是,使用这种模式的正确方法是什么(没有构造函数)?
答案 0 :(得分:3)
当你从另一个组件的Awake中调用MyMethod时可能会发生这种情况,因为Awake被称为before the game starts。我看到的唯一解决方案是确保您不在Awake()事件中调用其他组件(在本例中为MyMethod),而是在Start()事件中调用方法。
答案 1 :(得分:0)
Unity文档说“在游戏开始之前调用了唤醒”,但这并不精确。当场景中的游戏对象变为活动状态时,将调用组件的Awake方法。
默认情况下,加载场景时某些游戏对象将处于活动状态,但其他游戏对象可能稍后会被激活。然后就有可能通过AddComponent动态添加组件。
当依赖Awake和Start方法之间的依赖项时,应牢记这一方面。竞争条件的另一个示例是启用Update方法中的组件。虽然启用组件意味着将调用其Start方法,但在运行的更新周期中不会发生这种情况,因此其他组件无法依靠第一个组件的“ .enabled”属性来确定它是否已启动。