Unity3d編輯器擴展學習筆記

編輯器擴展編輯器

1.添加菜單欄:把特性應用於靜態方法

參數1:菜單名的空格後面是定義快捷鍵(單符號得用"_"開頭,組合鍵%=Ctrl,#=Shift,&=Alt)
參數2:經過定義一個驗證方法來控制是否啓用菜單欄(如:當有選擇到物體時,啓用,不然禁用)
參數3:菜單欄中顯示的順序(優先級),按這個值能夠分組(大概相差10就分一組)
能夠爲已有菜單添加子菜單,如Assets/MyTools,將顯示在Assets菜單欄內,同時也會在Projiect窗口的右鍵菜單內顯示。
[MenuItem("MyTools/test1 _t", false, 12)]
[MenuItem("MyTools/test2 %t", false, 12)]ide

2.利用Selection類的靜態方法,能夠在編輯器中獲取到當前所選擇的對象

3.利用Undo類的靜態方法,能夠執行一些能夠撤銷的操做

Undo.DestroyObjectImmediate(Selection.activeGameObject);ui

4.爲組件添加右鍵菜單欄

方式1:能夠爲自定義組件、內置組件添加
必須以「CONTEXT」開始,方法的參數MenuCommand mc會被自動賦值爲該組件所掛載的遊戲物體code

[MenuItem("CONTEXT/PlayerController/菜單名")]
static void ResetSize(MenuCommand mc)
{
    PlayerController pc = mc.context as PlayerController;
    //接下來就能夠修改組件對象pc的屬性了
    pc.Size = 12;
}

方式2:只能爲自定義組件添加(能夠編輯代碼的組件),直接在該組件的代碼內添加。
ContextMenu和ContextMenuItem類在UnityEngine命名空間下,與UnityEditor無關
a.爲組件添加右鍵菜單欄對象

[ContextMenu("Set Color")]
void SetColor()
{
    bodyColor = Color.red;
}

b.爲組件的屬性添加右鍵菜單欄遊戲

[ContextMenuItem("Menu name", "AddSize")]
public int Size = 0;

void AddSize()
{
    Size += 10;
}

5.自定義Inspector面板

using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
// 爲組件EnemyManager自定義Inspector面板顯示,CanEditorMutipleObjects 表示能夠同時編輯多個物體
[CustomEditor(typeof(EnemyManager)),CanEditMultipleObjects]
public class EnemyManagerInspector : Editor
{
    // 這裏用簡單的顯示控制來讓你們理解自定義編輯器的流程
    public static SerializedProperty enemyList, bossEnemyList,size;
    void OnEnable()
    {
        enemyList = serializedObject.FindProperty("EnemyList");
        bossEnemyList = serializedObject.FindProperty("BossEnemyList");
    }
    private bool isOpenDelete = false;
    private bool isOpenAdd = true;
    private bool isShow = false;
    public override void OnInspectorGUI()
    {
        //表示只作附加顯示,可爲內置組件附加新的Inspector面板屬性
        base.DrawDefaultInspector();
        // 更新編輯器顯示的序列化屬性
        serializedObject.Update();
        //獲取組件對象
        EnemyManager enemyManager = (EnemyManager)target;
        //顯示屬性,true表示顯示全部包含的成員
        EditorGUILayout.PropertyField(enemyList,true);
        //開始新的一行
        EditorGUILayout.BeginHorizontal();
        isOpenDelete = EditorGUILayout.BeginToggleGroup("是否容許刪除", isOpenDelete); //包含一組元素,總體控制他們是否可編輯
        if (GUILayout.Button("刪除成員"))
        {
        }
        EditorGUILayout.EndToggleGroup();
        EditorGUILayout.EndHorizontal();
        GUILayout.Label("**********分割線*********");
        // 接受序列化賦值
        serializedObject.ApplyModifiedProperties();
    }
}

6.自定義窗口

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class MyWindow : EditorWindow {
    [MenuItem("Window/show mywindow")]
    static void ShowMyWindow()
    {
        MyWindow window= EditorWindow.GetWindow<MyWindow>();
        window.Show();
    }
    private string name="";
    void OnGUI()
    {
        GUILayout.Label("這是個人窗口");
        name = GUILayout.TextField(name);
        if (GUILayout.Button("建立"))
        {
            GameObject go = new GameObject(name);
            //紀錄操做,便於撤銷
            Undo.RegisterCreatedObjectUndo(go, "create gameobject");
        }
    }
}

7.自定義對話窗口

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class EnemyChange : ScriptableWizard {
    [MenuItem("Tools/CreateWizard")]
    static void CreateWizard()
    {
        ScriptableWizard.DisplayWizard<EnemyChange>("統一修改敵人","Change And Close","Change");
    }
    public int changeStartHealthValue = 10;
    public int changeSinkSpeedValue = 1;
     const string changeStartHealthValueKey = "EnemyChange.changeStartHealthValue";
     const string changeSinkSpeedValueKey = "EnemyChange.changeSinkSpeedValue";
    //當窗口被建立出來的時候調用的
    void OnEnable()
     {
         changeStartHealthValue = EditorPrefs.GetInt(changeStartHealthValueKey, changeStartHealthValue);
         changeSinkSpeedValue = EditorPrefs.GetInt(changeSinkSpeedValueKey, changeSinkSpeedValue);
    }
    //檢測create按鈕的點擊
    void OnWizardCreate()
    {
        GameObject[] enemyPrefabs = Selection.gameObjects; //得到選擇的物體對象
        //顯示進度條
        EditorUtility.DisplayProgressBar("進度", "0/" + enemyPrefabs.Length + " 完成修改值", 0);
        int count = 0;
        foreach (GameObject go in enemyPrefabs)
        {
            CompleteProject.EnemyHealth hp = go.GetComponent<CompleteProject.EnemyHealth>();
            Undo.RecordObject(hp, "change health and speed");
            hp.startingHealth += changeStartHealthValue;
            hp.sinkSpeed += changeSinkSpeedValue;
            count++;
            EditorUtility.DisplayProgressBar("進度", count+"/" + enemyPrefabs.Length + " 完成修改值", (float)count/enemyPrefabs.Length);
        }
        EditorUtility.ClearProgressBar();
        //顯示提示信息
        ShowNotification(new GUIContent(Selection.gameObjects.Length + "個遊戲物體的值被修改了"));
    }
    //檢測Other按鈕的點擊
    void OnWizardOtherButton()
    {
        OnWizardCreate();
    }
    //當前字段值修改的時候會被調用
    void OnWizardUpdate()
    {
        errorString = null;
        helpString = null;
        if (Selection.gameObjects.Length > 0)
        {
            helpString = "您當前選擇了" + Selection.gameObjects.Length + "個敵人"; //頭部提示信息
        }
        else
        {
            errorString = "請選擇至少一個敵人"; //底部警告信息
        }
        //保存面板的修改
        EditorPrefs.SetInt(changeStartHealthValueKey, changeStartHealthValue);
        EditorPrefs.SetInt(changeSinkSpeedValueKey, changeSinkSpeedValue);
    }
    void OnSelectionChange()
    {
        OnWizardUpdate();
    }
}

8.其它

當腳本掛載到物體上時,自動爲它添加指定組件,如:[RequireComponent(typeof(Rigidbody))]
添加進菜單Component中,[AddComponentMenu("companentPathAndName")]ip

相關文章
相關標籤/搜索