常用的事件函数

1. 简介

Unity中的脚本组织不像传统的游戏循环,有一个持续进行的主循环并在循环体中处理游戏逻辑。

相对的,Unity 会在特定的事件发生时,调用脚本中特定的函数,然后执行逻辑的任务就交给了该脚本函数,函数执行完毕后,执行的权力重新还给Unty。

这些特定的函数通常被称为事件函数,因为是在特定事件发生时由引擎层调用的。

2.必然事件

事件函数 作用
Awake 脚本实例被创建时调用(用于游戏对象的初始化,注意Awake的执行早于所有脚本的Start函数)
Start Update函数第一次运行之前调用(用于游戏对象的初始化)
Reset 用户点击检视面板的Reset按钮或者首次添加该组件时被调用。此函数只在编辑模式下被调用。Reset最常用于在检视面板中给定一个最常用的默认值。
Update 每帧调用一次(用于更新游戏场景和状态)
FixedUpdate 每个固定物理时间间隔调用一次(用于物理引擎的参数更新)
LateUpdate 每帧调用一次,在Update之后(用于更新游戏场景和状态,和相机有关的更新一般放在这里)

2.1 Updata与FixedUpdate的区别

  • FixedUpdate

    物理更新的事件函数,物理引擎也会按照物理帧更新,机制和Update函数类似,但是更新的时机完全不同。

    它在每一次物理更新时被调用。

  • Updata

    帧更新函数,每帧调用一次。

要认识到,物理更新的频率和时机与Update函数是相对独立的。尽可能在FixedUpdate函数中进行物理相关的操作,在Update函数中进行其他操作,只有选择正确的函数才能让游戏效果尽可能准确。

2.1.1 帧率

每一帧所经历的时间并不是一个固定值,所以通过Updata函数控制物体移动的速度将不会是稳定的。

主要是因为硬件负载的原因,引擎默认会按照每秒60帧运行游戏,但是当负载增大时,帧率可能会下降,无法达到60帧,这时可能就只有30帧,帧率降低了一半,每帧的时间增加了一倍。物体的运动由于帧率降低而变慢了。实践中一般不允许这种情况的发生。

解决方案是将两帧之间的间隔Time.deltaTime考虑进去。

代码如下:

1
2
3
4
5
6
7
8
9
10
using UnityEngine;

public class ExampleScript : MonoBehaviour
{
public float distancePerSecond;
void Update ()
{
transform.Translate(0, 0,distancePerSecond*Time.deltaTime);
}
}

注意:通过乘以Time.deltaTime的运算,物体的移动不再以“每帧距离”为准,而变成了“每秒距离”。

物体移动的距离将根据每帧时间的长短而变化,从而在时间上看起来移动是匀速的。

2.1.2 物理帧率

与主更新函数Update不同,Unity的物理系统必须以固定的时间间隔工作,因为只有固定的时间间隔才能保证物理模拟的准确性。就算当前负载很高、帧率很低,Unity也会尽可能保证物理刷新的频率,因为如果物理刷新帧率无法保证,就可能出现不可预料的计算结果。

在主菜单的工程选项的TimeManager中可以修改物理更新的时间间隔。
在脚本中使用Time. fixedDeltaTime可以获得物理更新间隔。

较小的物理更新间隔会带来更高的更新频率,更准确、更细腻的运算结果,但是也会极大地增加硬件负担。
fixedDeltaTime 的默认值为0.02,当对物理运算的准确性非常在意时,可以考虑适当减小这个值。

3. 事件响应函数

函数名称 作用
OnMouseEnter 鼠标移入GUI控件或者碰撞体时调用
OnMouseOver 鼠标停留在GUI控件或者碰撞体时调用
OnMouseExit 鼠标移出GUI控件或者碰撞体时调用
OnMouseDown 鼠标在GUI控件或者碰撞体上按下时调用
OnMouseUp 鼠标按键释放时调用
OnTriggerEnter 与其他碰撞体进入触发器时调用
OnTriggerExit 与其他碰撞体离开触发器时调用
OnTriggerStay 当其他碰撞体停留在触发器时调用
OnCollisionEnter 当碰撞体或者刚体与其他碰撞体或者刚体接触时调用
OnCollisionExit 当碰撞体或者刚体与其他碰撞体或者刚体停止接触时调用
OnCollisionStay 当碰撞体或者刚体与其他碰撞体或者刚体保持接触时调用
OnControllerColliderHit 当控制器移动时与碰撞体发生碰撞时调用
OnDestroy 脚本销毁时调用
OnGUI 渲染GUI和处理GUI消息时调用
OnBecameVisible 对于任意一个相机可见时调用
OnBecameInVisible 对于任意一个相机不可见时调用
OnEnable 对象启用或者激活时调用
OnDisable 对象禁用或者取消激活时调用