橙子0012 发表于 2018-4-17 14:04:23

自定义Inspector检视面板

Unity中的Inspector面板可以显示的属性包括以下两类:
(1)C#以及Unity提供的基础类型;
(2)自定义类型,并使用关键字序列化,比如:

public class TestClass
{
    public Vector3 vec = Vector3.zero;
    public Color clr = Color.green;
}
  也可以使用标记不需要显示的属性,比如:

public class TestClass
{
   
    public Vector3 vec = Vector3.zero;
}
  有的时候对于U3D默认的Inspector不能满足需求,则可以对特定类型的Inspector面板进行自定义:编写
一个对应的Editor类,然后重写其OnInspector方法,比如我们有如下类型:

复制代码
using UnityEngine;
using System.Collections;


public class TestClass
{
    public Vector3 vec = Vector3.zero;
   
    public Color clr = Color.green;
}



public class TestInspector : MonoBehaviour
{
    public Vector3 lookAtPoint = Vector3.zero;
    public Vector3 pos = Vector3.zero;
    public TestClass testObj = new TestClass();

    void Update()
    {
      transform.LookAt(lookAtPoint);
      transform.position = pos;
    }
}
复制代码
  然后在Editor目录下添加如下脚本:

复制代码
using UnityEngine;
using UnityEditor;
using System.Collections;


public class TestInspectorEditor : Editor
{
    private SerializedObject obj;
    private SerializedProperty lookAtPoint;
    private SerializedProperty pos;
    private SerializedProperty testObj;

    // 添加TestInspector组件的GameObject被选中时触发该函数
    void OnEnable()
    {
      obj = new SerializedObject(target);
      lookAtPoint = obj.FindProperty("lookAtPoint");
      pos = obj.FindProperty("pos");
      testObj = obj.FindProperty("testObj");
    }

    // 重写Inspector检视面板
    public override void OnInspectorGUI()
    {
      obj.Update();

      EditorGUILayout.PropertyField(lookAtPoint);
      EditorGUILayout.PropertyField(pos);
      EditorGUILayout.PropertyField(testObj, true);   // 第二个参数表示有子节点需要显示

      obj.ApplyModifiedProperties();
    }

}
复制代码
  在OnInspector函数中就可以实现你想要的效果。

  上面的代码中有几点需要注意:

  (1)这个函数可以使代码在编辑模式下运行,不需要运行游戏;

  (2)TestInspectorEditor类必须继承自Editor,CustomEditor告诉U3D哪个组建类型需要自定义,OnI
nspectorGUI在显示组件的Inspector面板时调用;

  (3)SerializedObject序列化物体、SerializedProperty序列化属性和Editor这三者一起使用,用来访问
和更新组件的属性,SeriailzedProperty能够以通用的方式访问所有的基础类型,包括对数组的控制等;

  (4)可以在OnInspectorGUI中调用DrawDefaultInspector函数用来显示默认的监事面板内容;

  (5)EditorGUILayout.PropertyField(testObj, true);如果该类型有子节点,第二个参数需要设置为true
才能正确的展开;

   (6)也可用于隐藏属性显示。

******************************************************************************************

  除了自定义Inspector检视面板,我们还可以类似的方法自定义场景视图中对物体的控制,方法是重定
义Editor的OnSceneGUI()函数,比如:

复制代码
using UnityEngine;
using UnityEditor;
using System.Collections;


public class TestInspectorEditor : Editor
{

    private SerializedObject obj;
    private SerializedProperty lookAtPoint;
    private SerializedProperty pos;
    private SerializedProperty testObj;

    // 添加TestInspector组件的GameObject被选中时触发该函数
    void OnEnable()
    {
      obj = new SerializedObject(target);
      lookAtPoint = obj.FindProperty("lookAtPoint");
      pos = obj.FindProperty("pos");
      testObj = obj.FindProperty("testObj");
    }

    // 重写Inspector检视面板
    public override void OnInspectorGUI()
    {
      obj.Update();

      EditorGUILayout.PropertyField(lookAtPoint);
      EditorGUILayout.PropertyField(pos);
      EditorGUILayout.PropertyField(testObj, true);   // 第二个参数表示有子节点需要显示

      obj.ApplyModifiedProperties();
    }

    void OnSceneGUI()
    {
      // 绘制一条由target到世界坐标原点的直线,颜色为黄色
      Handles.color = Color.yellow;
      Handles.DrawLine((target as TestInspector).transform.position, Vector3.zero);
      // 创建一个位置控制柄
      Handles.PositionHandle(Vector3.zero, Quaternion.identity);
      // 创建一个滑动控制柄,可以沿某个方向滑动target
      Handles.Slider((target as TestInspector).transform.position, Vector3.zero);

      (target as TestInspector).transform.position = Handles.FreeMoveHandle((target as TestInspector).transform.position, Quaternion.identity, 2.0f, Vector3.zero, Handles.DrawRectangle);
      
      if (GUI.changed)
      {
            EditorUtility.SetDirty(target);
      }
    }

}

梦想家 发表于 2018-5-9 16:27:31

:victory:
页: [1]
查看完整版本: 自定义Inspector检视面板