Version: 5.6
Controlling GameObjects Using Components
时间和帧率管理

事件函数

A script in Unity is not like the traditional idea of a program where the code runs continuously in a loop until it completes its task. Instead, Unity passes control to a script intermittently by calling certain functions that are declared within it. Once a function has finished executing, control is passed back to Unity. These functions are known as event functions since they are activated by Unity in response to events that occur during gameplay. Unity uses a naming scheme to identify which function to call for a particular event. For example, you will already have seen the Update function (called before a frame update occurs) and the Start function (called just before the object’s first frame update). Many more event functions are available in Unity; the full list can be found in the script reference page for the MonoBehaviour class along with details of their usage. The following are some of the most common and important events.

常规更新事件

游戏很像动画,其中的动画帧是动态生成的。游戏编程中的一个关键概念是在渲染每帧之前改变游戏对象的位置、状态和行为。Update 函数是 Unity 中包含这种代码的主要位置。在渲染帧之前以及计算动画之前都会调用 Update 函数。

void Update() {
    float distance = speed * Time.deltaTime * Input.GetAxis("Horizontal");
    transform.Translate(Vector3.right * distance);
}

物理引擎也采用与帧渲染类似的方式以离散时间步骤进行更新。在每次物理更新之前都会调用一个称为 FixedUpdate 的单独事件函数。由于物理更新和帧更新不会以相同频率进行,所以如果将物理代码放在 FixedUpdate 函数而不是 Update 中,此代码将产生更准确的结果。

void FixedUpdate() {
    Vector3 force = transform.forward * driveForce * Input.GetAxis("Vertical");
    rigidbody.AddForce(force);
}

为场景中的所有对象调用 Update 和 FixedUpdate 函数之后以及计算所有动画之后,如果能进行其他更改,也会很有用。一个例子是摄像机应该聚焦于目标对象;必须在目标对象移动后才能调整摄像机的方向。另一个例子是脚本代码应该覆盖动画的效果(例如,让角色的头部看向场景中的目标对象)。可使用 LateUpdate 函数来处理这些类型的情况。

void LateUpdate() {
    Camera.main.transform.LookAt(target.transform);
}

初始化事件

如果能在游戏运行过程中进行任何更新之前调用初始化代码,通常会很有用。在第一帧之前或开始对象的物理更新之前需要调用 Start 函数。场景加载时会为场景中的每个对象调用 Awake 函数。请注意,虽然各种对象的 Start 和 Awake 函数的调用顺序是任意的,但在调用第一个 Start 之前,所有 Awake 都要完成。这意味着 Start 函数中的代码可以利用先前在 Awake 阶段执行的其他初始化。

GUI 事件

Unity 有一个系统用于渲染场景中主要操作的 GUI 控件,并响应对这些控件的点击。此代码的处理方式与正常的帧更新有些不同,因此应将此代码置于定期调用的 OnGUI 函数中。

void OnGUI() {
    GUI.Label(labelRect, "Game Over");
}

You can also detect mouse events that occur over a GameObject as it appears in the scene. This can be used for targeting weapons or displaying information about the character currently under the mouse pointer. A set of OnMouseXXX event functions (eg, OnMouseOver, OnMouseDown) is available to allow a script to react to user actions with the mouse. For example, if the mouse button is pressed while the pointer is over a particular object then an OnMouseDown function in that object’s script will be called if it exists.

物理事件

物理引擎将通过调用该对象的脚本上的事件函数来报告对象的碰撞情况。在进行接触、保持接触和中断接触时,将调用 OnCollisionEnterOnCollisionStayOnCollisionExit 函数。对象的碰撞体配置为触发器(即,碰撞体只检测某物何时进入而不进行物理反应)时,将调用相应的 OnTriggerEnterOnTriggerStayOnTriggerExit 函数。如果在物理更新期间检测到多次接触,可能连续多次调用这些函数,因此会将一个参数传递给函数,从而提供碰撞的详细信息(位置、进入对象标识等)。

void OnCollisionEnter(otherObj: Collision) {
    if (otherObj.tag == "Arrow") {
        ApplyDamage(10);
    }
}

Controlling GameObjects Using Components
时间和帧率管理