MonoBehaviour Lifecycle(生命周期/脚本执行顺序)

简介:



脚本执行顺序

前言

搭建一个示例来验证Unity脚本的执行顺序,大概测试以下部分:

  • 物理方面(Physics)
  • 渲染(Scene rendering)
  • 输入事件(InputEvent)

流程图

Unity文档:https://docs.unity3d.com/Manual/ExecutionOrder.html

原图地址:https://docs.unity3d.com/uploads/Main/monobehaviour_flowchart.svg

测试场景

搭建场景

示例下载:https://github.com/zhaoqingqing/blog_samplecode/raw/master/unity-framework/monobehaviour_lifecycle/monobehaviour_lifecycle.unitypackage

根据上图中的脚本生命周期,我编写三个脚本来测试部分阶段的生命周期:

  • Logs.cs 输出日志(可选)
  • TestInputEvent.cs(Input输入事件)
  • TestPhysicOrder.cs(物理事件执行顺序)
  • TestSceneRender.cs(Render顺序)

创建一个空的场景,创建三个Gameobject,每个gameobject上分别绑上要测试的脚本。每次测试不同的功能,分别激活不同的gameobject

打印调用堆栈脚本

可以打印调用方法的堆栈,包括方法名,文件名

github:https://github.com/zhaoqingqing/blog_samplecode/blob/master/unity-framework/monobehaviour_lifecycle/Logs.cs

using System;
using System.Diagnostics;

public class Logs  {

    /// <summary>
    /// 打印调用者的方法名
    /// </summary>
    public static void DoLog()
    {
        StackTrace st = new StackTrace(true);
        //获取当前调用的方法名
        StackFrame stackFrame = st.GetFrame(1);
        //var callInfo = string.Format("{0}:{1}.{2}",stackFrame.GetFileName(),stackFrame.GetFileLineNumber(),stackFrame.GetMethod().Name);
        var callInfo = stackFrame.GetMethod().Name.ToString();
        DoLog(callInfo);
    }

    public static void DoLog(string szMsg, params object[] args)
    {
        string log = string.Format("[{0}]{1}", DateTime.Now.ToString("HH:mm:ss.ffff"), string.Format(szMsg, args));
        UnityEngine.Debug.Log(log);
    }
}

物理测试

测试脚本

测试脚本中写了Unity的各个脚本函数,大致内容如下:

github:https://github.com/zhaoqingqing/blog_samplecode/blob/master/unity-framework/monobehaviour_lifecycle/TestPhysicOrder.cs

using System;
using UnityEngine;
using System.Collections;

public class TestPhysicOrder : MonoBehaviour
{
    // Reset to default values
    public void Reset()
    {
        Logs.DoLog();
    }

    // Awake is called when the script instance is being loaded
    public void Awake()
    {
        StartCoroutine(YieldOneFrame());
        StartCoroutine(YieldEndOfFrame());
        StartCoroutine(YieldWaitForFixedUpdate());
        Logs.DoLog();
    }

    // This function is called when the object becomes enabled and active
    public void OnEnable()
    {
        Logs.DoLog();
    }

    // Use this for initialization
    void Start()
    {
        Logs.DoLog();
    }

    // This function is called every fixed framerate frame, if the MonoBehaviour is enabled
    public void FixedUpdate()
    {
        Logs.DoLog();
    }

    // Update is called once per frame
    void Update()
    {
        Logs.DoLog();
    }

    IEnumerator YieldWaitForFixedUpdate()
    {
        yield return new WaitForFixedUpdate();
        Logs.DoLog("WaitForFixedUpdate");
    }

    IEnumerator YieldOneFrame()
    {
        yield return 1;
        Logs.DoLog("YieldOneFrame");
    }

    IEnumerator YieldEndOfFrame()
    {
        yield return new WaitForEndOfFrame();
        Logs.DoLog("YieldEndOfFrame");
    }

    // LateUpdate is called every frame, if the Behaviour is enabled
    public void LateUpdate()
    {
        Logs.DoLog();
    }

    // This function is called when the behaviour becomes disabled or inactive
    public void OnDisable()
    {
        Logs.DoLog();
    }

    // This function is called when the MonoBehaviour will be destroyed
    public void OnDestroy()
    {
        Logs.DoLog();
    }

    // Sent to all game objects when the player gets or looses focus
    public void OnApplicationFocus(bool focus)
    {
        Logs.DoLog();
    }

    // Sent to all game objects when the player pauses
    public void OnApplicationPause(bool pause)
    {
        Logs.DoLog();
    }

    // Sent to all game objects before the application is quit
    public void OnApplicationQuit()
    {
        Logs.DoLog();
    }

}

测试结果

开始部分截图

结束部分截图

Render测试

测试脚本

github:https://github.com/zhaoqingqing/blog_samplecode/blob/master/unity-framework/monobehaviour_lifecycle/TestSceneRender.cs

using System;
using UnityEngine;
public class TestSceneRender : MonoBehaviour
{

    // OnPreCull is called before a camera culls the scene
    public void OnPreCull()
    {
        Logs.DoLog();
    }

    // OnPreRender is called before a camera starts rendering the scene
    public void OnPreRender()
    {
        Logs.DoLog();

    }

    // Callback that is sent if an associated RectTransform has it's dimensions changed
    public void OnRectTransformDimensionsChange()
    {
        Logs.DoLog();
    }

    // Callback that is sent if an associated RectTransform is removed
    public void OnRectTransformRemoved()
    {
        Logs.DoLog();
    }

    // OnRenderImage is called after all rendering is complete to render image
    public void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        Logs.DoLog();
    }

    // OnRenderObject is called after camera has rendered the scene
    public void OnRenderObject()
    {
        Logs.DoLog();
    }


    // OnWillRenderObject is called once for each camera if the object is visible
    public void OnWillRenderObject()
    {
        Logs.DoLog();
    }

    // Implement this OnDrawGizmosSelected if you want to draw gizmos only if the object is selected
    public void OnDrawGizmos()
    {
        Logs.DoLog();
    }

    // OnGUI is called for rendering and handling GUI events
    public void OnGUI()
    {
        Logs.DoLog();
    }
}

测试结果

当把测试脚挂在Cube或者Camera上,会执行的函数是不相同的。

绑在Camera上

绑在Cube上


本文转自赵青青博客园博客,原文链接:http://www.cnblogs.com/zhaoqingqing/p/5990370.html,如需转载请自行联系原作者

相关文章
设置VSCode代码编辑器右侧的Minimap代码缩略图滚动条切换显示、隐藏的快捷键Alt+M
设置VSCode代码编辑器右侧的Minimap代码缩略图滚动条切换显示、隐藏的快捷键Alt+M
|
小程序
微信小程序文件上传无响应解决方法
微信小程序文件上传无响应解决方法
2207 0
|
自动驾驶 程序员 API
告别重复繁琐!Apipost参数描述库让API开发效率飙升!
在API开发中,重复录入参数占用了42%的时间,不仅效率低下还易出错。Apipost推出的参数描述库解决了这一痛点,通过智能记忆功能实现参数自动填充,如版本号、分页控制、用户信息等常用字段,大幅减少手动输入。支持Key-Value与Raw-Json格式导入,一键提取响应结果至文档,将创建20参数接口文档时间从18分钟缩短至2分钟。相比Postman需手动搜索变量,Apipost的参数复用响应速度仅0.3秒,且支持跨项目共享与实时纠错,真正实现“一次定义,终身受益”。
百万级高并发mongodb集群性能数十倍提升优化实践(上篇)
本文是oppo互联网某百亿级数据量/百万级高并发mongodb集群线上真实优化案例,荣获mongodb中文社区2019年度一等奖。
百万级高并发mongodb集群性能数十倍提升优化实践(上篇)
|
开发工具 git
git branch (branchname)
git branch (branchname) 是 Git 中创建和管理分支的一种命令。通过这个命令,你可以根据指定的分支名创建一个新的分支,或者跳转到已经存在的分支上。branchname 参数是可选的,如果不指定,则默认创建或切换到主分支(master 或 main)。
493 8
|
数据可视化 项目管理 数据库
一文看懂团队协作工具:谁能胜出2024榜单?
随着远程办公和数字化管理的普及,团队协作工具成为企业必备。本文深入评测了六款主流工具:板栗看板、Notion、Trello、Asana、ClickUp 和 Slack,从功能特色、优缺点、使用场景及性价比等方面进行分析,帮助你选择最适合团队的协作利器。
471 0
|
Java 编译器
封装,继承,多态【Java面向对象知识回顾①】
本文回顾了Java面向对象编程的三大特性:封装、继承和多态。封装通过将数据和方法结合在类中并隐藏实现细节来保护对象状态,继承允许新类扩展现有类的功能,而多态则允许对象在不同情况下表现出不同的行为,这些特性共同提高了代码的复用性、扩展性和灵活性。
封装,继承,多态【Java面向对象知识回顾①】
|
人工智能
TITAN:哈佛医学院推出多模态全切片病理基础模型,支持病理报告生成、跨模态检索
TITAN 是哈佛医学院研究团队开发的多模态全切片病理基础模型,通过视觉自监督学习和视觉-语言对齐预训练,能够在无需微调或临床标签的情况下提取通用切片表示,生成病理报告。
719 8
TITAN:哈佛医学院推出多模态全切片病理基础模型,支持病理报告生成、跨模态检索
|
Ubuntu Linux API
linux系统中使用QT实现摄像头功能的方法
linux系统中使用QT实现摄像头功能的方法
715 0
|
前端开发 JavaScript 程序员
2024年最新65% 的程序员竟都是自学成才?_为啥学技术都自学,2024年最新42岁程序员面试
2024年最新65% 的程序员竟都是自学成才?_为啥学技术都自学,2024年最新42岁程序员面试
2024年最新65% 的程序员竟都是自学成才?_为啥学技术都自学,2024年最新42岁程序员面试

热门文章

最新文章