腳本執行順序
前言
搭建一個示例來驗證Unity腳本的執行順序,大概測試以下部分:
- 物理方面(Physics)
- 渲染(Scene rendering)
- 輸入事件(InputEvent)
流程圖
Unity文檔:https://docs.unity3d.com/Manual/ExecutionOrder.html
原圖地址:https://docs.unity3d.com/uploads/Main/monobehaviour_flowchart.svg

測試場景
搭建場景
根據上圖中的腳本生命周期,我編寫三個腳本來測試部分階段的生命周期:
- Logs.cs 輸出日志(可選)
- TestInputEvent.cs(Input輸入事件)
- TestPhysicOrder.cs(物理事件執行順序)
- TestSceneRender.cs(Render順序)
創建一個空的場景,創建三個Gameobject,每個gameobject上分別綁上要測試的腳本。每次測試不同的功能,分別激活不同的gameobject

打印調用堆棧腳本
可以打印調用方法的堆棧,包括方法名,文件名
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的各個腳本函數,大致內容如下:
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測試
測試腳本
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上

