在開發時經常需要進行大量資源管理, 在編寫新程序及進行 Prefab 建構時這問題令開發者非常苦惱.
e.g. 建立一個多層架構的 Prefab, 把所有在 ScrollView 底下的 MyListElement 都放到 Array/List 的動作..
這些大量 Drag & Drop 的動作多做數次會令人發瘋.
這時候 OnValidate 就可以幫助開發者減少這些無謂的 setup 動作.
以 UGUI 的 Button 舉例.
ButtonLabel.cs
using UnityEngine; using UnityEngine.UI; public class ButtonLabel : MonoBehaviour { public Text m_Label; public Button m_Button; private void OnValidate() { if (m_Label == null) m_Label = GetComponentInChildren<Text>(true); if (m_Button == null) m_Button = GetComponentInChildren<Button>(true); } }
當這個 ButtonLabel 加入到 Button 上時候, 我們只要把其中一個 field 更動一下 { 放入 Text } 那麼 Button + Label 會一起自動找取底下第一順位的 Text 跟 Button.
但這個對於懶散慣了的程序員是不足夠的.
我們希望這個動作在 ButtonLabel 一開始放到 GameObject 身上時就自動執行一次.
在 Component 放到 GameObject 身上時會自動跑的 method 是 Reset();
所以我們修改如下:
public class ButtonLabel : MonoBehaviour { public Text m_Label; public Button m_Button; private void Reset() { AutoConfig(); } private void OnValidate() { AutoConfig(); } private void AutoConfig() { if (m_Label == null) m_Label = GetComponentInChildren<Text>(true); if (m_Button == null) m_Button = GetComponentInChildren<Button>(true); } }
首先 Reset() 在開發者重設 Component 時會被呼叫,
而 OnValidate() 在 “任何” 更改時也會被呼叫一次, 這包括編譯階段. 這間接導致 AutoConfig 在每次編譯時時也被呼叫.
單單一兩個 OnValidate 沒問太大負擔但想像一下你的專案有數千個 OnValidate 的元件每一個在 編譯時也被執行……..
這個測試會令 CPU 浪費很多非必要的檢測資源.
這個時候就需要用到另一個檢測手段.
UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode
用來得知是否正在編譯, 正在編譯就別進行了, 因為我們假設在 Reset 階段已經檢測過了及設定好了.
就別浪費每次對行 Playmode 測試的編譯資源.
using UnityEngine; using UnityEngine.UI; public class ButtonLabel : MonoBehaviour { public Text m_Label; public Button m_Button; private void Reset() { AutoConfig(); } private void OnValidate() { #if UNITY_EDITOR if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode) return; #endif if (!Application.isPlaying) AutoConfig(); } private void AutoConfig() { if (m_Label == null) m_Label = GetComponentInChildren<Text>(true); if (m_Button == null) m_Button = GetComponentInChildren<Button>(true); } }
因為 EditorApplication 只能在 UnityEditor 下才能取得. 所以程序又變得擁擠了.
當然有很多手法令這些檢測變得統一及簡化, 但各人有不同方式, 這不在本篇討論範圍.
好东西