> 技术文档 > Unity | 编辑器开发:Inspector扩展+独立窗口_unity oninspectorgui

Unity | 编辑器开发:Inspector扩展+独立窗口_unity oninspectorgui

目录

一、Inspector行为面板扩展

1.创建一个脚本

2.创建行为面板扩展的Editor脚本

(1)重写面板绘制方法

(2)获取序列化字段,并进行名称修改

(2.1)EditorGUILayout.PropertyField

(2.2)Update()与ApplyModifiedProperties()

(2.3)FindProperty方法

二、使用EditWindow自定义窗口


        编辑器工具大致可分为脚本Inspector的扩展和独立窗口两大部分,这两大部分又涉及SceneView绘制和Preview窗口绘制等。

一、Inspector行为面板扩展

1.创建一个脚本

        Enemy_Type1类有三个属性:血量、速度、攻击力,并有默认的初始值。

using UnityEngine;public class Enemy_Type1 : MonoBehaviour{ public int hp = 100; //血量 public float speed = 300;  //速度 public int atk = 10; //攻击力}

2.创建行为面板扩展的Editor脚本

        Editor脚本实现CustomEditor特性,并重写OnInspectorGUI方法。通过OnInspectorGUI方法的重写,我们可以为其自定义行为面板属性内容,比如增加几个按钮预设,方便初始化不同类型的参数。

  • CustomEditor是Unity编辑器中的一个特性,允许开发者为特定组件创建自定义的检视器界面,替代默认的Inspector面板。
  • [CustomEditor(typeof(目标组件类型))]特性关联目标组件。
  • OnInspectorGUI是CustomEditor类中的一个关键方法,负责绘制自定义的UI界面。每当Inspector面板需要刷新时,Unity会调用这个方法,所以在这里添加GUI元素可以实时更新显示。

(1)重写面板绘制方法

using UnityEditor;using UnityEngine;[CustomEditor(typeof(Enemy_Type1))] //这里链接到MonoBehaviour脚本public class Enemy_Type1Inspector : Editor{ ///  /// 重写面板绘制方法:增加几个按钮预设,方便初始化不同类型的参数 ///  public override void OnInspectorGUI() { base.OnInspectorGUI(); //获取绑定的MonoBehaviour脚本对象 var concertTarget = base.target as Enemy_Type1; if (GUILayout.Button(\"preset1\")) //角色属性预设1 { concertTarget.hp = 100; concertTarget.speed = 600; concertTarget.atk = 6; } if (GUILayout.Button(\"preset2\")) //角色属性预设2 { concertTarget.hp = 200; concertTarget.speed = 550; concertTarget.atk = 4; } }}

(2)获取序列化字段,并进行名称修改

(2.1)EditorGUILayout.PropertyField

        通过EditorGUILayout.PropertyField可将SerializedProperty序列化属性转化为Inspector面板的交互控件(如滑动条、勾选框等),无需手动编写不同数据类型的UI逻辑

EditorGUILayout.PropertyField(serializedObject.FindProperty(\"rotationSpeed\"));

        此代码会自动根据rotationSpeed字段的类型(如floatint)生成对应的控件,在Inspector面板进行展示。

(2.2)Update()与ApplyModifiedProperties()
  • Update():从目标对象读取最新属性值到SerializedObject中,保证数据同步。
  • ApplyModifiedProperties():将用户在Inspector的修改回写至实际对象,自动处理撤销操作和多对象批量修改。
(2.3)FindProperty方法

        通过字段名字符串获取SerializedProperty对象(如_previewAngle),需确保字段名称与脚本中的序列化字段完全匹配。

 public override void OnInspectorGUI() { serializedObject.Update(); //首先更新序列化对象 //生命值,序列化字段对象 var hpProp = serializedObject.FindProperty(\"hp\"); //速度,序列化字段对象 var speedProp = serializedObject.FindProperty(\"speed\"); //攻击力,序列化字段对象 var atkProp = serializedObject.FindProperty(\"atk\"); using (var change = new EditorGUI.ChangeCheckScope())//监测GUI内容改变 { EditorGUILayout.PropertyField(hpProp, new GUIContent(\"Enemy hp\")); EditorGUILayout.PropertyField(speedProp, new GUIContent(\"Enemy speed\")); EditorGUILayout.PropertyField(atkProp, new GUIContent(\"Enemy atk\")); //直接进行序列化字段绘制 if (GUILayout.Button(\"preset1\"))  //预设1按钮 { hpProp.intValue = 100; speedProp.floatValue = 600; atkProp.intValue = 6; } if (GUILayout.Button(\"preset2\"))  //预设2按钮 { hpProp.intValue = 200; speedProp.floatValue = 550; atkProp.intValue = 4; } if (change.changed) //如果改变则应用修改 { serializedObject.ApplyModifiedProperties(); } } }

二、使用EditWindow自定义窗口

        在Unity开发中我们还可以使用自定义窗口进行编辑器扩展。unity建议将自定义的插件启动项置于Tools目录下。附上一篇关于编辑器开发的文章:Unity | 编辑器开发-CSDN博客

using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEditor;public class MyWindows : EditorWindow{ //unity建议将自定义的插件启动项置于Tools目录中 [MenuItem(\"Tools/Battle Debuger\")] static void Setup() { //在这个静态方法中执行窗口的创建 GetWindow(); } void Awake() { //打开MyWindows窗口时,会调用Awake方法 Debug.Log(\"Awake\"); //事件委托,它会在 Scene 视图的每一帧 GUI 渲染时被调用。 SceneView.duringSceneGui += OnSceneGUIDelegateBind; } void OnDestroy() { //场景视图GUI取消绑定 SceneView.duringSceneGui -= OnSceneGUIDelegateBind; } void OnGUI() //绘制窗口的GUI内容 { if (GUILayout.Button(\"Generate Enemy_Type1\")) { //省略其他代码 } if (GUILayout.Button(\"Generate Enemy_Type1 x10\")) { //省略其他代码 } if (GUILayout.Button(\"Killed All Enemy\")) { //省略其他代码 } } void OnSceneGUIDelegateBind(SceneView sceneView) { Debug.Log(\"OnSceneGUIDelegateBind\"); var enemies = GetEnemies(); for (int i = 0; i < enemies.Length; i++) { var enemy = enemies[i]; //Unity的Handles类提供的绘图API,用于在Scene视图中绘制线框等图形,并且这些图形只在编辑器下可见,不影响运行时。 Handles.DrawWireCube(enemy.Position, new Vector3(0.5f, 1f, 0.5f)); }//将敌人以方块绘制出来 } struct EnemyInfo { public Vector3 Position { get; set; } } //调试数据 EnemyInfo[] GetEnemies() { return new EnemyInfo[] { new EnemyInfo() { Position = new Vector3(0f, 0f, 0f) }, new EnemyInfo() {  Position = new Vector3(1.5f, 0f, 0f) } }; }}

——本文总结自微信读书《Unity3D动作游戏开发实战》