Unity 3D基于组件的设计模型和竞争条件

时间:2013-07-09 12:55:07

标签: c# unity3d race-condition

我在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();

有时,并非总是如此,MyMethodStart之前执行,所以我最终要做的就是将我在Start中通常拥有的所有初始化移到MyMethod一个丑陋的解决方法:

    void Start() { }

    void MyMethod() 
    {
        entity = (MyType)FindObjectsOfType(typeof(MyType)).First();
        var x = entity.SomeProperty; // <= now it's fine.
    }

我的问题是,使用这种模式的正确方法是什么(没有构造函数)?

2 个答案:

答案 0 :(得分:3)

当你从另一个组件的Awake中调用MyMethod时可能会发生这种情况,因为Awake被称为before the game starts。我看到的唯一解决方案是确保您不在Awake()事件中调用其他组件(在本例中为MyMethod),而是在Start()事件中调用方法。

答案 1 :(得分:0)

Unity文档说“在游戏开始之前调用了唤醒”,但这并不精确。当场景中的游戏对象变为活动状态时,将调用组件的Awake方法。

默认情况下,加载场景时某些游戏对象将处于活动状态,但其他游戏对象可能稍后会被激活。然后就有可能通过AddComponent动态添加组件。

当依赖Awake和Start方法之间的依赖项时,应牢记这一方面。竞争条件的另一个示例是启用Update方法中的组件。虽然启用组件意味着将调用其Start方法,但在运行的更新周期中不会发生这种情况,因此其他组件无法依靠第一个组件的“ .enabled”属性来确定它是否已启动。