在非活动/停用的游戏对象上启动协程

Any*_*nya 1 c# unity-game-engine

我有以下代码:

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

IEnumerator Load()
{
    yield return new WaitForSeconds(waitTime);
    gameObject.SetActive(true);
}
Run Code Online (Sandbox Code Playgroud)

这给了我一个错误:

协程无法启动,因为游戏对象“NameOfObj”处于非活动状态!

这是有道理的,因为游戏对象已在运行脚本之前设置为停用。即便如此,那我该怎么办呢?我gameObject.SetActive(false)之前尝试过转移到协程WaitForSeconds()。这样做会完全阻止游戏对象加载。

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

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

Pro*_*mer 6

您无法从 GameObject 已停用的脚本启动协程函数。

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

有两种方法可以做到这一点

1 . 使用不太可能被停用的现有游戏对象。就我而言,我通常使用相机。我访问相机,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());
Run Code Online (Sandbox Code Playgroud)

2 . 将脚本附加到空游戏对象,空游戏对象上的脚本将控制或能够激活/停用其他游戏对象。

您希望在停用的游戏对象上运行具有协程函数的脚本(将其附加到您想要停用的游戏对象):

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

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

创建一个空的游戏对象,然后将以下脚本附加到它:

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

协程现在从另一个名为 的脚本启动LoadFuncCallerScript


Tri*_*cko 5

为了避免停止协程,我所做的就是让游戏对象不会被停用。

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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