[英]C# Coroutine doesnt works in Unity
我正在尝试制作一个基本的平台游戏,但我的关卡控制器脚本不起作用,它需要先加载加载场景,然后再加载下一个关卡,但它会不断加载下一个关卡
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class LevelController : MonoBehaviour
{
[SerializeField] string nextLevel;
private Gem[] gems;
void OnEnable()
{
gems = FindObjectsOfType<Gem>();
}
IEnumerator Wait()
{
yield return new WaitForSeconds(3);
}
void Update()
{
if (ReadyToNextLevel())
{
SceneManager.LoadScene("Loading");
StartCoroutine(Wait());
SceneManager.LoadScene(nextLevel);
}
}
bool ReadyToNextLevel()
{
foreach (var gem in gems)
{
if (gem.gameObject.activeSelf)
{
return false;
}
}
return true;
}
}
您的代码中有两个大问题。
启动协程不延迟启动该程序的方法!
如果您希望在协程完成后发生某些事情,您需要将其移动到例程本身中或使用回调。
然而,问题是:您正在加载一个新场景,即“加载”场景 -> 当前场景已卸载 -> 该脚本所在的对象被销毁 -> 例程将不再执行。
除了您的对象是DontDestroyOnLoad
从您的代码看来并非如此。
因此,为了解决这两个问题,您需要确保在加载另一个场景时不会破坏此对象,至少在完成加载过程之前不会。
你可以这样做,例如
public class LevelController : MonoBehaviour
{
[SerializeField] string nextLevel;
private Gem[] gems;
void OnEnable()
{
gems = FindObjectsOfType<Gem>();
// Makes sure this is not destroyed when another scene is load
DontDestroyOnLoad(gameObject);
}
bool alreadyLoading;
IEnumerator Wait(Action whenDone)
{
yield return new WaitForSeconds(3);
// invoke the callback action
whenDone?.Invoke();
}
void Update()
{
if (ReadyToNextLevel() && ! alreadyLoading)
{
alreadyLoading = true;
SceneManager.LoadScene("Loading");
StartCoroutine(Wait(() =>
{
// This will be done after the routine finished
SceneManager.LoadScene(nextLevel);
// Now we don't need this object anymore
Destroy(gameObject);
}));
}
}
bool ReadyToNextLevel()
{
foreach (var gem in gems)
{
if (gem.gameObject.activeSelf)
{
return false;
}
}
return true;
}
}
编辑:请参阅 derHugo 的回答。 他们比我更熟悉 Unity,并指出您的脚本将在场景更改时卸载。
您的Wait()
协程立即产生,因此StartCoroutine(Wait())
将立即返回并加载下一个场景。
如果你想在加载之前等待三秒钟,那么将加载放在协程中。
像这样:
private bool isLoading;
void Update()
{
if (!isLoading && ReadyToNextLevel())
StartCoroutine(LoadNextLevel());
}
IEnumerator LoadNextLevel()
{
isLoading = true;
SceneManager.LoadScene("Loading");
yield return new WaitForSeconds(3);
SceneManager.LoadScene(nextLevel);
isLoading = false;
}
有关更多详细信息,请参阅协程帮助
这不起作用有两个原因,首先当您加载到加载场景中时,游戏对象被销毁,因为您还没有告诉它DontDestroyOnLoad
,因此脚本将从当前场景中“删除”。 其次,当你调用协程时,它会调用协程,然后立即继续下一行代码,它不会等待协程完成才继续。 我认为 derHugo 涵盖了如何解决这些问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.