1. 程式人生 > >Unity3D開發之編譯器Inspector面板擴充套件開發

Unity3D開發之編譯器Inspector面板擴充套件開發

沒有系統性的研究unity編譯器的擴充套件開發,所以就是遇到什麼需求就去研究什麼需求。之前寫過一兩次,後來沒怎麼用就忘記了。這次開發專案又遇到同樣需求,我百度了半天好容易找到答案。心想這次還是記錄下來,下次可以直接回顧掌握了。

一。最近在做模擬教學的內容。涉及到步驟操作檢測。比如我們不開啟總電源開關,我們無法開啟電燈電視機電風扇。所以我們要在對每一個可互動物件操作之前都要進行判斷是否滿足可操作的條件。我們會在被操作物件上掛上一個我們自寫的一個條件限制類,比如LimitSetting,程式碼如下:

public class LimitSetting : MonoBehaviour
{
    public LimitList limits;
 
    public bool CheckLimits()
    {
        //foreach(LimitMembers limit in limits.members)
        //{
        //    if(limit的條件不符合) return false;
        //}
        return true;
    }
}

[Serializable]
public class LimitList
{
    public List<LimitMembers> members = new List<LimitMembers>();
}
[Serializable]
public class LimitMembers
{
    public StepContrl stepContrl;
    public int RightState;
}

當我們將此指令碼掛在操作物體上時,Inspector面板如下:

我們需要幾個條件就可以往裡新增幾個。但是我們可能會覺得這個介面不夠直觀化,想要做成Button的那種可以點選+新增的那種。如下:

這時候就需要我們擴充套件Inspector面板了。程式碼如下:記住編輯完程式碼要放在Editor資料夾下才可以在編譯器模式下執行。

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEditorInternal;

[CustomEditor(typeof(LimitSetting))]

public class LimitSettingEditor : Editor
{

    // Use this for initialization
    private ReorderableList m_LimitList;
    private void OnEnable()
    {
        m_LimitList = new ReorderableList(serializedObject,
            serializedObject.FindProperty("limits").FindPropertyRelative("members"),
            true, true, true, true);
        m_LimitList.drawElementCallback += DrawNameElement;
        m_LimitList.drawHeaderCallback = (Rect rect) =>
        {
            GUI.Label(rect, "新增執行條件");
        };
    }
    private void DrawNameElement(Rect rect, int index, bool selected, bool focused)
    {
        SerializedProperty element = m_LimitList.serializedProperty.GetArrayElementAtIndex(index);

        rect.y += 2;
        rect.height = EditorGUIUtility.singleLineHeight;
        EditorGUI.PropertyField(new Rect(rect.x, rect.y, 200, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("stepContrl"), GUIContent.none);
        EditorGUI.PropertyField(new Rect(rect.x + 200, rect.y, 100, EditorGUIUtility.singleLineHeight), element.FindPropertyRelative("RightState"), GUIContent.none);
    }
    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        m_LimitList.DoLayoutList();

        serializedObject.ApplyModifiedProperties();
    }
}

其實這個功能的用處不是很大,也不是必須。如果時間充裕可以自己編輯下,為了專案的美觀化,直觀化。

二。當我們在面板上新增欄位值的時候,我們發現一些Object上根本不需要新增一些對應的資訊。就直接為空了。當面板對外公開的欄位較多時我們就容易花了眼填錯行。這時候我們就可以根據各自需求顯示自己需要的欄位屬性。比如我們寫一個Test資料類指令碼,程式碼如下:

public class Test : MonoBehaviour
{
    public bool UseProperty = false;
    public float speed = 0.5f;
    public string Name = "";

}

當我們在面板點選UseProperty為true時,才會顯示speed和Name。當為false時,隱藏speed和Name。程式碼如下:

using System.Collections;
using System.Collections.Generic;
using UnityEditor;

[CustomEditor(typeof(Test)), CanEditMultipleObjects]
public class TestEditor : Editor {

    static SerializedProperty UseProperty, speed, Name;

    private void OnEnable()
    {
        UseProperty = serializedObject.FindProperty("UseProperty");
        speed = serializedObject.FindProperty("speed");
        Name = serializedObject.FindProperty("Name");
    }

    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        EditorGUILayout.PropertyField(UseProperty);
        if (UseProperty.boolValue==true)
        {
            EditorGUILayout.PropertyField(speed);
            EditorGUILayout.PropertyField(Name);
        }
        serializedObject.ApplyModifiedProperties();
    }
 }

同樣此程式碼要放到Editor資料夾下才會在編輯器環境下執行。