浅谈Unity脚本生命周期与执行顺序
作者:iwiniwin 时间:2022-05-22 00:47:34
一、脚本生命周期
Unity脚本中的常见必然事件如下表所示
名称 | 触发时机 | 用途 |
---|---|---|
Awake | 脚本实例被创建时调用 | 用于游戏对象的初始化,注意Awake的执行早于所有脚本的Start函数 |
OnEnable | 当对象变为可用或激活状态时被调用 | 用途 |
Start | Update函数第一次运行之前调用 | 用于游戏对象的初始化 |
Update | 每帧调用一次 | 用于更新游戏场景和状态 |
FixedUpdate | 每个固定物理时间间隔调用一次 | 用于物理状态的更新 |
LateUpdate | 每帧调用一次(在update之后调用) | 用于更新游戏场景和状态,和相机有关的更新一般放在这里 |
OnGUI | 渲染和处理OnGUI事件 | 用途 |
OnDisable | 当前对象不可用或非激活状态时被调用 | 用途 |
OnDestroy | 当前对象被销毁时调用 | 用途 |
下面将以代码来看看这些必然事件的调用时机
新建一个C#脚本,并添加以下代码,然后将其挂到任意的游戏对象上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestTest : MonoBehaviour
{
private void Awake()
{
Debug.Log("Awake");
}
private void OnEnable()
{
Debug.Log("OnEnable");
}
// Start is called before the first frame update
void Start()
{
Debug.Log("Start");
}
// Update is called once per frame
void Update()
{
Debug.Log("Update");
}
private void FixedUpdate()
{
Debug.Log("FixedUpdate");
}
private void LateUpdate()
{
Debug.Log("LateUpdate");
}
private void OnGUI()
{
Debug.Log("OnGUI");
}
private void OnDisable()
{
Debug.Log("OnDisable");
}
private void OnDestroy()
{
Debug.Log("OnDestroy");
}
}
打印结果如下图示:
可以发现,Awake, Start函数都是在游戏对象被创建时调用一次。
当游戏过程中调整脚本的可见状态时,会分别调用OnEnable, OnDisable函数,而Awake和Start将不会再调用,也就是说一旦脚本被挂载上以后,Awake和Start有且仅会被执行一次。
而Update, FixedUpdate, LateUpdate, OnGUI函数是会在游戏过程中被多次调用的(日志窗口右侧的数字表示该条日志信息打印的次数)。
最后在游戏对象被销毁时,会依次调用OnDisable, OnDestory函数。
二、MonoBehavior生命周期图
下面再放上一张的生命周期图
三、脚本执行顺序
在游戏开发中,不可避免的会使用许多脚本,那么如何确定不同脚本之间调用的先后顺序呢
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test1 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Debug.Log("start 1");
}
private void Awake()
{
Debug.Log("awake 1");
}
// Update is called once per frame
void Update()
{
Debug.Log("update 1");
}
}
将上面的代码依次添加到Test1, Test2和Test3脚本中(适当修改打印的日志),并挂载到不同的游戏对象上。
挂载的顺序为先挂载Test3,再挂载Test2,最后挂载Test1
打印结果如下图所示
打印结果是先打印Test1的,再打印Test2,最后打印Test3。
其实脚本的执行顺序与挂载到游戏对象上的先后顺序有关。最先被挂载的最后执行,最后被挂载的最先执行(如果读者有疑惑,可以不断调整脚本的挂载顺序,看日志打印与上述结论是否相符)。
需要注意的是,无论多个脚本的执行顺序如何,但所有脚本的Awake函数一定会比所有的Start函数先执行完,所有的Start函数一定也会比所有的Update函数先执行完,其他有顺序的生命周期函数也是类似的(从上图的日志信息中也可以看出)。
四、自定义执行顺序
有时可能有这样的需求,A脚本中的属性实例化可能需要用到B脚本中的属性,所以在A脚本属性实例化时,必须保证B脚本已经被实例化完毕。当然我们可以通过先挂在A脚本再挂载B脚本来实现。但在实际开发中,用到的脚本中多,很难去记住各个脚本挂载的先后顺序。所以Unity提供了Script Execution Order配置项,来配置多个脚本的执行顺序。
在工程面板中任意点击选中一个脚本文件,在属性面板中会出现该脚本的详细信息,选择右上角的Execution Order...
,打开如下图所示界面
点击“+”可以添加脚本,为其设置order值,order值越小的越先执行,order值越大的越后执行
来源:https://www.cnblogs.com/iwiniwin/p/10799836.html