前言

Monobehavior生命周期函数表网上都有,这里只研究经常遇到的,重点关注FixedUpdate、Update、LateUpdate与OnGUI

public class MonoLifeTest : MonoBehaviour
{
    private void Awake() // 最先调用,只调用一次,只依赖于脚本所附属的物体,与脚本的激活状态无关,也就是说只要所属物体是激活的,无论脚本是否处于激活状态都会调用
    {
        Debug.LogError("Awake");
    }
    private void OnEnable() // 脚本或脚本附属的物体被激活时调用,重复改变状态重复调用
    {
        Debug.LogError("OnEnable");
    }
    private void Start() // Update之前调用,只调用一次
    {
        Debug.LogError("Start");
    }
    private void FixedUpdate() // 固定时间间隔调用,在update之前,循环调用多次,适合处理一些物理逻辑,但不要滥用
    {
        Debug.LogError("FixedUpdate");
    }
    private void Update() // 每渲染帧调用一次,与设备的性能以及渲染的物体有关,也就是说不同性能的设备的调用间隔不同,所以导致了相同的游戏在不同的设备上的表现不同
    {
        Debug.LogError("Update");
    }
    private void LateUpdate() // 在Update调用之后调用,调用多次,可用于摄像机跟随
    {
        Debug.LogError("LateUpdate");
    }
    private void OnGUI() // 在Update与LateUpdate之后调用,每帧调用多次,用于渲染和处理GUI事件,同其它函数一样在脚本处于非激活状态时不执行
    {
        Debug.LogError("OnGUI");
    }
    private void OnDisable() // 在取消脚本激活状态时调用一次
    {
        Debug.LogError("OnDisable");
    }
    private void OnDestroy() // 销毁脚本及脚本所属物体时调用一次,同Awake的地方在于只要脚本所属物体是处于激活状态,即使脚本属于非激活状态,销毁时也会调用
    {
        Debug.LogError("OnDestroy");
    }
}

在这里插入图片描述

Awake与OnDestroy

1.我们将脚本设为非激活状态,将脚本所属物体设为激活状态
在这里插入图片描述运行游戏

在这里插入图片描述
删除物体
在这里插入图片描述
或者删除脚本
在这里插入图片描述
可以发现只要脚本所属物体处于激活状态,无论脚本是否处于激活状态都会执行里面的Awake与OnDestroy方法,其它方法不执行
2. 我们将脚本处于激活状态,脚本所属物体处于非激活状态
在这里插入图片描述
运行游戏

在这里插入图片描述
发现所有函数都没有输出,那是因为物体(载体)没有激活
我很好奇此时MonoLifeTest的实际激活状态,所以我调整了一下结构将Directional Light设为Main Camera的父物体(否则采用GameObject.Find找不到隐藏物体),并写了一个辅助脚本FindScriptTest挂在Directional Light上如图
在这里插入图片描述

public class FindScriptTest : MonoBehaviour
{
    void Start()
    {
        //GameObject monoLifeTestGo = GameObject.Find("Main Camera");
        //GameObject monoLifeTestGo = GameObject.FindGameObjectWithTag("MainCamera");
        GameObject monoLifeTestGo = transform.Find("Main Camera").gameObject;
        if (monoLifeTestGo != null)
        {
            Debug.LogError("找到了Main Camera");
            MonoLifeTest script = monoLifeTestGo.GetComponent<MonoLifeTest>();
            if (script != null)
            {
                Debug.LogError("找到了MonoLifeTest");
                Debug.LogError("MonoLifeTest脚本的状态:" + script.enabled);
            }
        }
        else
        {
            Debug.LogError("没找到Main Camera");
        }
    }
}

运行游戏
在这里插入图片描述
可以看到MonoLifeTest脚本本身确实是激活状态
3. 总结:Awake与OnDestroy的调用仅受脚本所属物体的激活状态控制,而其它函数则需要脚本和所属物体都处于激活状态才会调用

OnGUI

官方解释:OnGUI在渲染和处理GUI事件时调用,可能会在每个渲染帧中调用多次

OnGUI is called for rendering and handling GUI events. This means that your OnGUI implementation might be called several times per frame (one call per event).

在这里插入图片描述
另外,当移动鼠标到Game视图区域,或者改变Game视图的大小时OnGUI仍会调用,不会因为游戏处于暂停状态而终止,其它每帧调用的函数却不会,测试OnDisable与OnDestroy也会
在这里插入图片描述

Time.deltaTime

官方解释:完成上一帧所消耗的秒数,只读

The time in seconds it took to complete the last frame (Read Only).

    private void FixedUpdate()
    {
        Debug.LogError("FixedUpdate:" + Time.deltaTime.ToString());
    }
    private void Update()
    {
        Debug.LogError("Update:" + Time.deltaTime.ToString());
    }
    private void LateUpdate()
    {
        Debug.LogError("LateUpdate:" + Time.deltaTime.ToString());
    }
    private void OnGUI()
    {
        Debug.LogError("OnGUI:" + Time.deltaTime.ToString());
    }

在这里插入图片描述
可以看出Update、LateUpdate与OnGUI共用一个时间增量即渲染帧增量,FixedUpdate自己用一个时间增量即固定帧增量,可在Edit->Project Settings->Time->Fixed Timestep中修改
在这里插入图片描述

FixedUpdate的调用间隔

那么FixedUpdate的调用间隔真的是恰好的0.02s吗?

    private float m_LastTime;
    private float m_NowTime;
    private float m_Offset;
    private void FixedUpdate()
    {
        m_NowTime = Time.realtimeSinceStartup;
        m_Offset = m_NowTime - m_LastTime;
        m_LastTime = m_NowTime;
        Debug.LogError("FixedUpdate:" + m_Offset.ToString());
    }

在这里插入图片描述
可以看出FixedUpdate的调用间隔并非固定的0.02s

总结

  1. FixedUpdate->Update->LateUpdate->OnGUI
  2. Awake与OnDestroy的调用仅受脚本所属物体的激活状态控制,而其它函数则需要脚本和所属物体都处于激活状态才会调用
  3. OnGUI在游戏暂停的状态下也有可能触发
  4. Time.deltaTime的值分为渲染帧和固定帧,Update、LateUpdate与OnGUI共用一个渲染帧增量,是每帧都在变化的,FixedUpdate自己用一个固定帧增量是固定的一般是0.02s,可手动设置
  5. FixedUpdate的调用间隔实际上并非是固定的
Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐