在非活动/停用的GameObject上启动协程

时间:2018-10-25 23:35:49

标签: c# unity3d

我有以下代码:

void Start()
{
    gameObject.SetActive(false);
    StartCoroutine(Load());
}

IEnumerator Load()
{
    yield return new WaitForSeconds(waitTime);
    gameObject.SetActive(true);
}

这给了我一个错误:

  

协程无法启动,因为游戏对象“ NameOfObj”   不活跃!

这很有意义,因为在运行脚本之前已将游戏对象设置为停用。即使如此,我该怎么办呢?我尝试在gameObject.SetActive(false)之前将WaitForSeconds()移至协程。这样做完全停止了游戏对象的加载。

据我了解,当执行gameObject.SetActive(false)行时,脚本将停止运行,直到重新激活游戏对象。但是,如果是这种情况,那么重新激活游戏对象(因为禁用了脚本)不是不可能吗?

无论如何,在游戏开始后我如何将我的游戏对象的加载延迟到2-3(或任意时间长度)?

2 个答案:

答案 0 :(得分:1)

您不能从已禁用其GameObject的脚本中启动协程函数。

StartCoroutine函数是MonoBehaviour类下的函数。当您必须在已停用的GameObject上启动协程时,您需要引用具有活动GameObject的MonoBehaviour对象。

两种方法

1 。使用不太可能被停用的现有GameObject。就我而言,我通常使用相机。我访问了相机的MonoBehaviour,因为它可能已被激活,然后使用它来启动协同程序功能。

我建议您使用此方法。

Start函数中的代码替换为以下代码:

//De-activate this GameObject
gameObject.SetActive(false);
//Get camera's MonoBehaviour
MonoBehaviour camMono = Camera.main.GetComponent<MonoBehaviour>();
//Use it to start your coroutine function
camMono.StartCoroutine(Load());

2 。将脚本附加到一个空的GameObject上,该空GameObject上的脚本将控制或能够激活/停用另一个GameObject。

带有协程函数的脚本,您希望在停用的GameObject上运行(将其附加到要停用的GameObject上):

public class YourDeactivatableScript: MonoBehaviour
{
    public IEnumerator Load()
    {
        yield return new WaitForSeconds(waitTime);
        gameObject.SetActive(true);
    }
}

现在,假设您要停用名为“ Cube” 的GameObject,该游戏对象已附加了YourDeactivatableScript脚本,但仍然能够启动其Load协程函数,使用新脚本创建一个空的GameObject,然后从中启动Load函数。

创建一个空的GameObject,然后将此脚本附加到它:

public class LoadFuncCallerScript: MonoBehaviour
{
    GameObject targetObject;

    public void Start()
    {
         //Find the GameObject you want to de-activate
        targetObject = GameObject.Find("Cube");
        //De-activate it
        targetObject.SetActive(false);
        //Get it's component/script
        YourDeactivatableScript script = targetObject.GetComponent<YourDeactivatableScript>();
        //Start coroutine on the other script with this MonoBehaviour
        StartCoroutine(script.Load());
    }
}

协程现在从另一个名为LoadFuncCallerScript的脚本开始。

答案 1 :(得分:0)

为避免停止协程,我要做的是拥有一个不会停用的游戏对象。

public class CoroutineHandler : MonoBehaviour
{
    private static CoroutineHandler instance = null;
    public static CoroutineHandler Instance
    {
        get
        {
            if(instance == null)
            {
                GameObject inst = new GameObject("CoroutineHandler");
                DontDestroyOnLoad(inst);
                instance = inst.AddComponent<CoroutineHandler>();
            }
            return instance;
        }
    }
}

然后使用CoroutineHandler.Instance.StartCoroutine(RoutineMethodHere());将其用于此类协程。

如果您不想要这样的东西,因为如果处理不正确,它可能会出错或引起泄漏,您可以尝试使用Invoke("MethodName", delay);