📝

扩展默认组件和资源的 Inspector 视图

之前介绍的扩展方法都是扩展自定义创建的脚本对应的 Inspector 面板,实际上开发者也可以通过一些方法来扩展 Unity 内部的组件或者资源对应的 Inspector 面板。

扩展默认组件

这里以扩展 Unity 内置的 Camera 组件为例,在不修改原有控件的前提下扩展 Camera 组件,增加一个随机设置位置的简单功能。

在空场景中添加一个名为 Camera 的物体,然后在 Inspector 中添加一个 Camera 组件:

首先实现该主要功能,即在一个确定的范围内随机产生一个位置,然后将 Camera 的位置修改为该位置:

Vector3 GenerateRandomPosition (float boundX, float boundY, float boundZ) {
		return new Vector3 (
				Random.Range (-boundX, boundX),
				Random.Range (-boundY, boundY),
				Random.Range (-boundZ, boundZ)
		);
}

void SetCameraPosition (Camera camera, Vector3 position) {
		camera.transform.position = position;
}

然后在新建脚本 Tools/DefaultComponents/Editor/CameraExtensionInspector.cs 中添加编辑器类和 Inspector 绘制逻辑:

using UnityEngine;
using UnityEditor;

namespace InspectorExtension.CameraExtensionInspector {
		[CustomEditor (typeof (Camera))]
		public class CameraExtensionInspector : Editor {
	
				Camera _target;
		
				private void OnEnable () {
						_target = (Camera)target;
				}
		
				public override void OnInspectorGUI () {
						if (GUILayout.Button ("Set Camera Randomly")) {
								Vector3 randomPosition = GenerateRandomPosition (10, 10, 10);
								SetCameraPosition (_target, randomPosition);
						}
				}
		}
}

编译后发现 Inspector 视图中只绘制了按钮,原本的控件都不见了,原因是自定义的绘制代码将会覆盖原有的绘制过程:

为不影响原控件的绘制,需要在自定义的绘制代码中添加原有的绘制过程:

public override void OnInspectorGUI () {
		base.DrawDefaultInspector ();

		if (GUILayout.Button ("Set Camera Randomly")) {
				Vector3 randomPosition = GenerateRandomPosition (10, 10, 10);
				SetCameraPosition (_target, randomPosition);
		}
}

此时编译后 Inspector 试图如下:

根据之前扩展 Inspector 面板的实例可知,新的绘制逻辑由重写的 OnInspectorGUI 确定,而哪个组件将被重新绘制,则是由整个类之前的 CustomEditor 属性决定的:

public CustomEditor(Type inspectedType);
public CustomEditor(Type inspectedType, bool editorForChildClasses);

inspectedType 即为对应重新绘制的组件的类型, editorForChildClasses 表示该类型的子类是否也会显示该编辑器。

基于此,实际上可以通过 CustomEditor 扩展各种类型的组件,包括开发者自定义的组件和 Unity 内置的组件。

扩展默认资源

鼠标点击 Project 中的资源或资源文件夹时,Inspector 面板也会有对应不同的显示:

根据之前的讨论,修改 CustomEditor 中的参数即可自定义对应组件的绘制逻辑。同样道理,只要找到这些默认资源对应的类型,就可以扩展其 Inspector 面板。

通过查阅 Unity 官方文档和相关资料,可以得知默认资源对应的类型,下表列举了部分常用的默认资源对应的类:

常用默认资源及其对应类

资源类型对应类文件后缀
场景资源SceneAsset.unity
图片资源TextureImporter.jpg .png
音效资源AudioImporter .mp3 .sfx
脚本资源MonoScript .cs .js .lua
文件夹或暂无确定类型的资源DefaultAsset无文件后缀或 Unity 无法识别的后缀

将默认资源对应的类的类型以参数的形式传入 CustomEditor 后,即可通过重写绘制函数自定义修改 Inspector 视图。作为一个例子,现对场景资源的 Inspector 面板进行简单的自定义:

using UnityEditor;

namespace InspectorExtension.DefaultAssets {
		[CustomEditor (typeof (SceneAsset))]
		public class DefaultAssetsInspector : Editor {
	
				SceneAsset _target;
		
				private void OnEnable () {
						_target = (SceneAsset)target;
				}
		
				public override void OnInspectorGUI () {
						EditorGUILayout.HelpBox ("This is a Unity scene named \"" + _target.name + "\".", MessageType.None);
				}
		}
}