從2017開始,在editor腳本中查找屬性是這樣寫的 var m_Script = serializedObject.FindProperty("m_Script");
SerializedProperty
以UGUI的源碼為例
using UnityEngine;
using UnityEngine.UI;
using UnityEditor.AnimatedValues;
namespace UnityEditor.UI
{
[CustomEditor(typeof(Selectable), true)]
/// <summary>
/// Custom Editor for the Selectable Component.
/// Extend this class to write a custom editor for an Selectable-derived component.
/// </summary>
public class SelectableEditor : Editor
{
protected virtual void OnEnable()
{
SerializedProperty m_Script = serializedObject.FindProperty("m_Script");
SerializedProperty m_InteractableProperty = serializedObject.FindProperty("m_Interactable");
}
}
}
直接修改
而我在unity4.x時,查找某個屬性是這樣寫的,我在Unity2019和Unity2020中測試目前這種寫法還是生效的
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(MyActor))]
public class MyActorInspector : Editor
{
public int ATKProp;
void OnEnable()
{
MyActor myActor = target as MyActor; //類型轉換為MyActor
ATKProp = myActor.ATK;//緩存對象的某個字段和屬性
}
public override void OnInspectorGUI()
{
ATKProp = EditorGUILayout.IntSlider("ATK", ATKProp, 0, 100);
}
}
這兩種寫法有什么區別呢?
serializedObject.FindProperty可以修改private的值,而直接修改只能訪問public的值
SerializedProperty被編輯的對象需要加上[Serializable]標簽,且要找的屬性如果是private需要加上[SerializeField]標簽,否則序列化會報錯
SerializedProperty寫法的值在編輯過程中可以撤消(Undo)、Prefab overrides,而直接修改無法撤消,就是按Ctrl+Z無效,所以建議平時還是使用FindProperty開發。
SerializedProperty中指向當前對象叫 serializedObject ,在直接寫叫 target
SerializedProperty文檔:https://docs.unity.cn/cn/current/ScriptReference/SerializedObject.html
在官網文檔中也有提到這兩種寫法的區別:https://docs.unity.cn/cn/current/ScriptReference/Editor.html
SerializedProperty文檔
// 更新序列化屬性,寫在OnInspectorGUI的開頭
serializedObject.Update ();
//對序列化屬性修改后,需要應用修改才能保存序列化數據,要寫在OnInspectorGUI方法的結尾
serializedObject.ApplyModifiedProperties ();
遇到問題
serializedObject復選框無法勾選
比如下面這段代碼就會讓復選框無法操作
protected override void OnEnable()
{
base.OnEnable();
UseLangId = serializedObject.FindProperty("useLangId");
}
public override void OnInspectorGUI()
{
EditorGUILayout.PropertyField(UseLangId,"使用語言包"); //這樣會導致Inspector的復選框,無法勾選和取消
serializedObject.Update();//NOTE 這句要放在最前面,否則無法操作復選框
serializedObject.ApplyModifiedProperties();
base.OnInspectorGUI();
}
EditorGUI.indentLevel是什么意思?
增加縮進深度,就是在這個屬性的開頭會有空格,需要配套出現,示例如下:
++EditorGUI.indentLevel;
for (int i = 0; i < paramArr.arraySize; i++)
{
paramArr.GetArrayElementAtIndex(i).stringValue = EditorGUILayout.TextField(paramArr.GetArrayElementAtIndex(i).stringValue);
args[i] = paramArr.GetArrayElementAtIndex(i).stringValue;
}
--EditorGUI.indentLevel;
