Unity对象初始化同步

时间:2019-06-28 17:22:48

标签: c# unity3d initialization

到目前为止,我一直在编码,认为monobehaviour中的函数将按以下顺序执行:

  

OnEnable>开始>更新> OnDisable

问题在于我认为此顺序将是绝对,这意味着在一个函数没有完全完成之前,下一个函数就无法开始执行。

  1. 第一个问题是:是这样吗?在update结束之前不会执行start吗?

然后我的问题出现在不同的monobehaviour类之间的同步中。

我有一个在其start函数中创建一些对象(基本上是菜单)的类。然后在另一个类中,我有一个类似的代码,但它也依赖,该类由第一个类创建的对象已经存在。我收到错误消息,因为尚未找到对象。

  

NullReferenceException:对象引用未设置为对象ShopHandler.Start()的实例(在Assets / Scripts / Shops / ShopHandler.cs:60)

所以现在我被困住了。因此,我的第二个问题是,

  1. 当我的不同班级依赖其他人时,如何同步我的班级

最后,还必须问这两个问题:

  1. update函数是否可以在这些类中的任何一个中执行,而它们却以某种方式“等待”其初始化部分,无论是在start函数,OnEnable函数中还是其他函数中?

当然,update函数依赖于已经初始化的对象,这可能会导致新的问题。

预先感谢

3 个答案:

答案 0 :(得分:2)

  

问题是我认为该顺序是绝对的,这意味着在一个函数没有完全完成之前,下一个函数就无法开始执行。

     
    

第一个问题是:是这样吗?在开始结束之前不会执行更新吗?

  

通常是的,但是有一个例外。

如果将Start实现为协程,则可以在Update以相同的单行为结束之前调用Start

例如,此代码:

IEnumerator Start() 
{
    Debug.Log("Start beginning");

    yield return null;

    Debug.Log("Start continuing");

    yield return null;

    Debug.Log("Start completing");    
}

void Update() 
{
    Debug.Log("Update running");
}  

可以产生以下输出:

  

从头开始
  开始继续
  更新正在运行
  开始完成
  更新正在运行
  更新正在运行
  更新正在运行
  ...

答案 1 :(得分:1)

这是我的方法:

假设您有两个单性行为A和B。假设B必须在A之后初始化。

1-)创建一个函数,即“ Initialise”,并在B而不是Start函数中使用它:

df = {}
for item in data:
    if 'features' in item:
        if 'properties' in item:
            nn = item.get("properties").get("PRI_NEIGH")
        if 'geometry' in item:
            coords = item.get('geometry').get('coordinates')
            df[nn] = coords

df_n=pd.DataFrame(df)

2-)在A obj中引用B obj,在准备好初始化后使用bObj.Initialise:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class B : MonoBehaviour
{

    public void Initialise()
    {
        //Code you run on Start()    
    }

}

最后,如果您希望在任何时候运行Update函数,我通常更喜欢使用某些东西作为标志。因此,这是我的第二个B类版本,用于控制update()行为:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class A : MonoBehaviour
{
    public B bObj;
    // Start is called before the first frame update
    void Start()
    {
        //Things to do in Start()
        //...
        //...
        //...
        bObj.Initialise();
    }

}

答案 2 :(得分:0)

很难说出问题的实际出处,因为您尚未发布任何代码。但是,我相信您可以通过实施2

中指出的解决方案来解决您的问题
  1. 是的,如果启用/激活了游戏对象/单行为,则在更新功能之前调用所有“开始功能”(和“唤醒”)!未激活的游戏对象上不会调用开始/唤醒/更新

  2. 您应该查看Script Execution Order。在这里,您可以确保按特定顺序调用类的启动/唤醒/更新功能。它应该在项目设置下列出。

  3. 初始化场景时,将在所有唤醒/开始功能完成后调用更新(除非将它们定义为协程,但这可能不是您的问题)。