我正在尝试开发一个事件驱动的游戏。起初我创建了一个带有一堆事件的单例,例如与当前关卡相关的所有事件。
public class LevelEvents : MonoBehaviour
{
public static LevelEvents instance;
public event Action onLevelRead;
public event Action onLevelSerialized;
private void Awake()
{
instance = this;
}
public void LevelRead()
{
if (onLevelRead != null)
{
onLevelRead();
}
}
public void LevelSerialized()
{
if (onLevelSerialized != null)
{
onLevelSerialized();
}
}
}
我想创建一个从读取关卡文件到序列化关卡的事件链。所以这些事件似乎非常简单。
我的 LevelReader 是入口点并在读取文件后调度事件。
public class LevelReader : MonoBehaviour
{
void OnEnable()
{
SceneManager.sceneLoaded += ReadLevelFile;
}
private void OnDestroy()
{
SceneManager.sceneLoaded -= ReadLevelFile;
}
private void ReadLevelFile(Scene scene, LoadSceneMode loadSceneMode)
{
// not implemented yet
LevelEvents.instance.LevelRead();
Destroy(gameObject);
}
}
序列化器将监听事件并序列化关卡。之后,它将为下一个脚本调度序列化事件
public class LevelSerializer : MonoBehaviour
{
private void Start()
{
LevelEvents.instance.onLevelRead += SerializeLevel;
}
private void OnDestroy()
{
LevelEvents.instance.onLevelRead -= SerializeLevel;
}
private void SerializeLevel()
{
// not implemented yet
LevelEvents.instance.LevelSerialized();
Destroy(gameObject);
}
}
那么问题来了。读取器在场景加载后调度读取事件。序列化程序将在启动时监听此事件。为时已晚,序列化程序将不会收到通知。我不能使用 Awake,因为这是事件单例注册 (LevelEvents) 所必需的。
想过不监听sceneLoaded事件,在Start方法中调用ReadLevelFile方法。这仍然为时已晚,因为 LevelReader 的 Start 方法被触发,Serializer 仍然不会收到通知。
如何在触发每个 Start 方法后运行 ReadLevelFile 方法?我希望得到比我的方法更好的解决方案:
- 在 X 秒后调用此方法(计时器很危险)
- 运行一次 Update 方法(我认为这是一个糟糕的解决方案)
- 编写一个系统来跟踪每个 EventSubscriber 并在每个 EventSubscriber 启动其 Start 方法后触发第一个方法(这个逻辑太多了,不是吗?)
- 定义脚本执行顺序(我认为这是一个糟糕的解决方案)
最佳答案
关于 unity docs ...
Start is called before the first frame update only if the script instance is enabled.
基于此,您可以使用协程等待下一帧开始,如下所示:
public class LevelReader : MonoBehaviour
{
// ...
void Start()
{
StartCoroutine(ReadLevelFileAfterFirstFrameCoroutine());
}
private IEnumerator ReadLevelFileAfterFirstFrameCoroutine()
{
yield return new WaitForEndOfFrame();
// Call read level file.
}
// ...
}
只需确保脚本实例实际已启用,如文档所述。
如果需要,您也可以在 Awake
中调用协程。它将在所有 Awake
和 Start
被调用后运行。
关于c# - 运行所有 Start 方法后创建事件链,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57543674/