我有以下代码:
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(或任意时间长度)?
答案 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);