用 Unity 构建模拟系统 – 事件函数的执行顺序

一、万物之源——MonoBehaviour类

MonoBehaviour 是 Unity 中所有脚本的基类,它提供了一系列用于实现游戏对象行为的功能。通过继承 MonoBehaviour,用户可以创建自定义的脚本,以控制游戏对象的生命周期、响应事件和管理游戏逻辑。它具有以下主要功能:

  1. 生命周期管理MonoBehaviour 提供了一系列的事件函数(如 Awake()Start()Update() 等),帮助开发者管理对象的生命周期。

  2. 组件系统Unity 使用组件化的设计,MonoBehaviour 允许你将功能模块化,便于在不同的游戏对象之间重用代码。

  3. 访问 Unity API通过 MonoBehaviour,可以直接访问 Unity 的许多功能,如物理引擎、渲染系统和输入管理。

  4. 协程支持MonoBehaviour 支持协程,允许你在一段时间内执行代码,而不会阻塞主线程。

二、什么是脚本生命周期?

脚本生命周期是指 Unity 中 MonoBehaviour 脚本的执行顺序时间点。了解脚本生命周期对于编写有效的游戏逻辑至关重要。以下是 MonoBehaviour 的主要生命周期事件函数及其顺序,具体其他事件函数的执行周期可以参考Unity说明文档的具体内容:

1. Awake()

  • 调用时机:脚本实例被加载时。
  • 用途:用于初始化变量或状态,通常在游戏对象启用之前执行。

2. OnEnable()

  • 调用时机:对象启用时。
  • 用途:可以在此处订阅事件或进行初始化操作。

3. Start()

  • 调用时机:在第一次更新之前调用。
  • 用途:用于进行一次性初始化,确保所有引用已设置。

4. Update()

  • 调用时机:每一帧调用一次。
  • 用途:处理每帧需要更新的逻辑,例如输入处理和对象移动。

5. FixedUpdate()

  • 调用时机:每固定时间间隔调用。
  • 用途:适用于物理计算(如 Rigidbody 的移动),因为它以固定频率执行。

6. LateUpdate()

  • 调用时机:在所有 Update 调用之后。
  • 用途:用于相机跟随等需要在所有其他更新后执行的操作。

7. OnDisable()

  • 调用时机:对象禁用时。
  • 用途:通常用于取消事件订阅或清理资源。

8. OnDestroy()

  • 调用时机:对象销毁之前调用。
  • 用途:用于释放资源或执行清理工作。

三、什么是时间函数?

事件函数是 Unity 中 MonoBehaviour 类提供的一组特殊方法,用于响应特定事件或条件。这些函数在特定的上下文中被自动调用,允许开发者实现游戏对象的动态行为。以下是一些常见的事件函数及其用途:

  1. Awake():在脚本实例被加载时调用。常用于初始化变量。

  2. OnEnable():当游戏对象启用时调用。适合进行事件订阅或初始化。

  3. Start():在第一次更新之前调用。用于一次性初始化。

  4. Update():每帧调用一次。处理每帧需要更新的逻辑,如输入处理和移动。

  5. FixedUpdate():每固定时间间隔调用。适合物理计算,例如 Rigidbody 的移动。

  6. LateUpdate():在所有 Update 调用之后调用。用于相机跟随等需要在其他更新后执行的操作。

  7. OnDisable():当对象被禁用时调用。用于取消事件订阅或清理资源。

  8. OnDestroy():在对象销毁之前调用。用于释放资源或执行清理工作。

物理和碰撞事件:

  1. OnCollisionEnter():当物体发生碰撞时调用。
  2. OnCollisionExit():当物体停止碰撞时调用。
  3. OnTriggerEnter():当物体进入触发器时调用。
  4. OnTriggerExit():当物体离开触发器时调用。

用户输入事件:

  1. OnMouseDown():当鼠标点击游戏对象时调用。

OnMouseUp():当鼠标释放点击时调用。

四、代码范例

在前一篇博客中我们介绍了协程(Coroutine),在本范例中我们将通过代码理解Unity中关键事件函数的执行流程。


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ExecutionSequence : MonoBehaviour
{

    int counter;// start is called before the first frame updatevoid start()

    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine("myCoroutine"); 
        print("start ends.");
    }

    // Update is called once per frame
    void Update()
    {
        if (counter < 10) print("frame:" + counter++);
    }

    IEnumerator myCoroutine() 
    {
        print("step1");
        yield return null;
        print("step2"); 
        print("step3");

    }

}

执行顺序如下:
  1. 首先,Start 方法首先被调用,协程 myCoroutine 启动,控制台输出 “step1” 。
  2. 执行完yield return null; 退出协程函数,暂停在下一帧(下一次Update执行后)继续执行。控制台输出 “start ends.”。
  3. Update 方法第一次调用, counter 由0开始计数,首先在控制台输出”frame: 0″ 。
  4. 当 Update 方法运行到下一帧时(第二次调用),控制台输出”frame: 1″ 。
  5. 协程继续执行,控制台打印输出 “step2” 和 “step3″。至此协程所有内容执行完毕。
  6. Update 方法再次调用,直到 counter 达到 9。

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注