Unity Editor開發中查找屬性的兩種寫法對比


從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;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM