知识点来源:总结人间自有韬哥在, 唐老狮,豆包
Unity中,Editor为特殊文件夹,使用UnityEditor命名空间的脚本需放此,避免打包报错。
菜单栏
[MenuItem("页签/选项")]
修饰静态函数[MenuItem("教程/TestFun")] static void TestFun() { Debug.Log("TestFun"); }
Hierarchy窗口
[MenuItem("GameObject/页签/选项")]
[MenuItem("GameObject/教程/TestFun2")] static void TestFun2() { Debug.Log("TestFun2"); }
Project窗口
[MenuItem("Assets/页签/选项")]
[MenuItem("Assets/教程/TestFun3")] static void TestFun3() { Debug.Log("TestFun3"); }
[AddComponentMenu("选项")]
修饰继承MonoBehaviour的脚本[AddComponentMenu("教程/Lesson02")] public class Lesson02 : MonoBehaviour {}
[MenuItem("CONTEXT/脚本名/页签/选项")]
[MenuItem("CONTEXT/Lesson02/教程/TestFun4")] static void TestFun4() { Debug.Log("TestFun4"); }
单键:路径后加 “ _ 按键”;组合键:用 %
(ctrl)、#
(shift)、&
(alt)
[MenuItem("教程/TestFun5 _F4")] static void TestFun5() { Debug.Log("TestFun5"); }
在 UnityEditor
命名空间下,我们通过创建一个继承自 EditorWindow
的类来实现自定义窗口。例如:
using UnityEditor;
public class Lesson03_自定义窗口拓展 : EditorWindow
{
private void OnGUI()
{
GUILayout.Label("测试文本");
if (GUILayout.Button("测试按钮"))
{
Debug.Log("Test");
}
}
}
我们可以使用添加自定义页签的方式来开启窗口,这需要通过调用 EditorWindow.GetWindow
方法来创建窗口对象。该方法有多种重载形式,主要参数包括:
true
,可创建浮动实用程序窗口(这种窗口可自由拖动和改变大小);若为 false
,则创建正常窗口。EditorWindow
类型的数组。创建窗口对象后,调用其 Show
方法即可显示窗口。示例代码如下:
using UnityEditor;
public class Lesson03_自定义窗口拓展 : EditorWindow
{
[MenuItem("编辑器拓展教程/Lesson03_自定义窗口拓展/显示Lesson03自定义窗口")]
private static void ShowWindow()
{
Lesson03_自定义窗口拓展 win = EditorWindow.GetWindow<Lesson03_自定义窗口拓展>();
win.titleContent = new GUIContent("我的窗口");
win.Show();
}
// 其他代码...
}
继承 EditorWindow
的窗口类自带一些事件回调函数,当相应事件触发时会自动执行:
回调函数 | 触发时机 | 示例代码 |
---|---|---|
OnHierarchyChange() |
当场景中的层次结构(Hierarchy)发生变化,如游戏对象的创建、删除或重命名时调用。 | private void OnHierarchyChange() { Debug.Log("当Hierarchy窗口内容发生变化时"); } |
OnFocus() |
窗口获得焦点时调用,可在此执行相关操作。 | private void OnFocus() { Debug.Log("获取焦点"); } |
OnLostFocus() |
窗口失去焦点时调用,常用于执行清理工作。 | private void OnLostFocus() { Debug.Log("失去焦点"); } |
OnProjectChange() |
项目资源发生变化,如添加、删除或修改项目文件时调用。 | private void OnProjectChange() { Debug.Log("当Project窗口内容发生变化时"); } |
OnInspectorUpdate() |
检视器(Inspector)面板更新时调用,可用于更新显示信息。 | private void OnInspectorUpdate() { Debug.Log("当Inspector窗口内容发生变化时"); } |
OnSelectionChange() |
选择的对象发生变化时调用,可执行与所选对象相关的操作。 | private void OnSelectionChange() { Debug.Log("当选中对象发生变化时"); } |
生命周期函数 | 触发时机 | 用途 | 示例代码 |
---|---|---|---|
OnEnable() |
窗口被激活时调用,通常在窗口创建时执行一次,用于进行初始化工作,如注册事件监听器或设置初始变量。 | 进行初始化操作 | private void OnEnable() { // 初始化操作 } |
OnGUI() |
每帧都会调用,用于绘制编辑器窗口的 GUI,使用 GUILayout 或 EditorGUILayout 等类创建界面元素。 |
绘制界面相关元素 | private void OnGUI() { // 绘制界面元素 } |
OnDestroy() |
窗口被销毁时调用,如关闭编辑器或切换场景时触发,用于进行最终的清理工作,释放未释放的资源。 | 执行清理操作 | private void OnDestroy() { // 清理操作 } |
Update() |
编辑器窗口每帧更新时调用,用于执行每帧需要进行的逻辑。 | 处理每帧相关逻辑 | private void Update() { // 每帧逻辑 } |
静态变量
静态变量 | 描述 | 示例代码 |
---|---|---|
focusedWindow |
当前已获得键盘焦点的 EditorWindow (只读)。 |
EditorWindow currentFocusedWindow = EditorWindow.focusedWindow; |
mouseOverWindow |
当前在鼠标光标下的 EditorWindow (只读)。 |
EditorWindow currentMouseOverWindow = EditorWindow.mouseOverWindow; |
静态函数
静态函数 | 描述 | 示例代码 |
---|---|---|
CreateWindow |
创建窗口,可用于创建非单例唯一的窗口。 | Lesson03_自定义窗口拓展 newWindow = EditorWindow.CreateWindow |
GetWindow |
创建单例唯一的窗口对象。 | Lesson03_自定义窗口拓展 singletonWindow = EditorWindow.GetWindow |
GetWindowWithRect |
返回一个指定位置、大小的窗口。 | Rect rect = new Rect(100, 100, 200, 200); Lesson03_自定义窗口拓展 sizedWindow = EditorWindow.GetWindowWithRect |
HasOpenInstances |
检查编辑器窗口是否打开。 | bool isOpen = EditorWindow.HasOpenInstances |
成员变量
成员变量 | 描述 | 示例代码 |
---|---|---|
titleContent |
用于设置窗口标题名。 | win.titleContent = new GUIContent("新标题"); |
position |
存储窗口的位置和大小信息。 | Rect currentPos = win.position; win.position = new Rect(200, 200, 300, 300); |
wantsMouseEnterLeaveWindow |
若设置为 true ,鼠标进入或离开窗口时,窗口会收到一次 OnGUI 调用。 |
win.wantsMouseEnterLeaveWindow = true; |
成员函数
成员函数 | 描述 | 示例代码 |
---|---|---|
Show |
显示面板。 | win.Show(); |
Repaint |
重绘窗口。 | win.Repaint(); |
Close |
关闭窗口。 | win.Close(); |
静态变量
变量名 | 描述 | 示例代码 |
---|---|---|
focusedWindow |
当前获得键盘焦点的 EditorWindow (只读) |
EditorWindow currentFocusedWindow = EditorWindow.focusedWindow; |
mouseOverWindow |
当前鼠标光标下的 EditorWindow (只读) |
EditorWindow currentMouseOverWindow = EditorWindow.mouseOverWindow; |
静态函数
函数名 | 描述 | 示例代码 |
---|---|---|
CreateWindow |
创建非单例唯一的窗口 | Lesson03_自定义窗口拓展 newWindow = EditorWindow.CreateWindow |
GetWindow |
创建单例唯一的窗口对象 | Lesson03_自定义窗口拓展 singletonWindow = EditorWindow.GetWindow |
GetWindowWithRect |
返回指定位置、大小的窗口 | Rect rect = new Rect(100, 100, 200, 200); Lesson03_自定义窗口拓展 sizedWindow = EditorWindow.GetWindowWithRect |
HasOpenInstances |
检查编辑器窗口是否打开 | bool isOpen = EditorWindow.HasOpenInstances |
成员变量
变量名 | 描述 | 示例代码 |
---|---|---|
titleContent |
设置窗口标题名 | win.titleContent = new GUIContent("新标题"); |
position |
存储窗口位置和大小信息 | Rect currentPos = win.position; win.position = new Rect(200, 200, 300, 300); |
wantsMouseEnterLeaveWindow |
设为 true 时,鼠标进出窗口会收到一次 OnGUI 调用 |
win.wantsMouseEnterLeaveWindow = true; |
成员函数
函数名 | 描述 | 示例代码 |
---|---|---|
Show |
显示面板 | win.Show(); |
Repaint |
重绘窗口 | win.Repaint(); |
Close |
关闭窗口 | win.Close(); |
布局选项
类型 | 描述 | 示例代码 |
---|---|---|
固定宽高 | 设置控件固定宽度和高度 | GUILayout.Width(300); GUILayout.Height(200); |
最小宽高 | 设置控件最小宽度和高度 | GUILayout.MinWidth(50); GUILayout.MinHeight(50); |
最大宽高 | 设置控件最大宽度和高度 | GUILayout.MaxWidth(100); GUILayout.MaxHeight(100); |
水平拓展 | 设置控件水平拓展属性 | GUILayout.ExpandWidth(true); GUILayout.ExpandHeight(false); |
文本与选择控件
控件类型 | 子类型 | 描述 | 示例代码 |
---|---|---|---|
文本控件 | 带标题内容文本 | 显示带标题和内容的文本 | EditorGUILayout.LabelField("文本标题", "测试内容"); |
普通文本 | 显示普通文本 | EditorGUILayout.LabelField("文本内容"); |
|
层级、标签选择 | 层级选择 | 选择游戏对象层级 | int变量 = EditorGUILayout.LayerField("层级选择", int变量); |
标签选择 | 选择游戏对象标签 | string变量 = EditorGUILayout.TagField("标签选择", string变量); |
|
枚举选择控件 | 枚举单选 | 单选枚举值 | 枚举变量 = (枚举类型)EditorGUILayout.EnumPopup("枚举选择", 枚举变量); |
枚举多选 | 多选枚举值 | 枚举变量 = (枚举类型)EditorGUILayout.EnumFlagsField("枚举多选", 枚举变量); |
|
整数选择控件 | 整数单选 | 从给定选项中单选整数 | int变量 = EditorGUILayout.IntPopup("整数单选框", int变量, 字符串数组, int数组); |
输入与关联控件
控件类型 | 子类型 | 描述 | 示例代码 |
---|---|---|---|
各类型输入控件 | 数值输入 | 输入不同数值类型 | int变量 = EditorGUILayout.IntField("Int输入框", int变量); long变量 = EditorGUILayout.LongField("long输入框", long变量); float变量 = EditorGUILayout.FloatField("Float 输入:", float变量); double变量 = EditorGUILayout.DoubleField("double 输入:", double变量); |
文本及向量输入 | 输入文本和向量 | string变量 = EditorGUILayout.TextField("Text输入:", string变量); vector2变量 = EditorGUILayout.Vector2Field("Vec2输入: ", vector2变量); vector3变量 = EditorGUILayout.Vector3Field("Vec3输入: ", vector3变量); vector4变量 = EditorGUILayout.Vector4Field("Vec4输入: ", vector4变量); rect变量 = EditorGUILayout.RectField("rect输入: ", rect变量); bounds变量 = EditorGUILayout.BoundsField("Bounds输入: ", bounds变量); boundsInt变量 = EditorGUILayout.BoundsIntField("Bounds输入: ", boundsInt变量); |
|
Delayed输入控件 | 输入值延迟生效 | i2 = EditorGUILayout.DelayedIntField("Int输入框", i2); |
|
对象关联控件 | - | 关联游戏对象或资源对象 | 对象变量 = EditorGUILayout.ObjectField(对象变量, typeof(对象类型), 是否允许关联场景上对象资源) as 对象类型; |
交互与提示控件
控件类型 | 子类型 | 描述 | 示例代码 |
---|---|---|---|
按钮控件 | 按下触发按钮 | 按下按钮触发操作 | EditorGUILayout.DropdownButton(new GUIContent("按钮上文字"), FocusType.Passive) |
开关控件 | 普通开关 | 普通开关按钮 | bool变量 = EditorGUILayout.Toggle("普通开关", bool变量); |
开关在左侧 | 开关在文字左侧的按钮 | bool变量 = EditorGUILayout.ToggleLeft("开关在左侧", bool变量); |
|
开关组控件 | - | 一组相关开关 | bool变量 = EditorGUILayout.BeginToggleGroup("开关组", bool变量); 其他控件绘制 EditorGUILayout.EndToggleGroup(); |
滑动条控件 | 浮点滑动条 | 选择浮点数值范围 | float变量 = EditorGUILayout.Slider("滑动条", float变量, 最小值, 最大值); |
整数滑动条 | 选择整数值范围 | int变量 = EditorGUILayout.IntSlider("整数值滑动条", int变量, 最小值, 最大值); |
|
双块滑动条控件 | - | 选择数值范围区间 | EditorGUILayout.MinMaxSlider("双块滑动条", ref 左侧值, ref 右侧值, 最小值, 最大值); |
帮助框控件 | 一般提示 | 显示一般提示信息 | EditorGUILayout.HelpBox("一般提示", MessageType.None); |
感叹号提示 | 显示带感叹号提示信息 | EditorGUILayout.HelpBox("感叹号提示", MessageType.Info); |
|
警告符号提示 | 显示带警告符号提示信息 | EditorGUILayout.HelpBox("警告符号提示", MessageType.Warning); |
|
错误符号提示 | 显示带错误符号提示信息 | EditorGUILayout.HelpBox("错误符号提示", MessageType.Error); |
其他控件
控件类型 | 描述 | 示例代码 |
---|---|---|
折叠控件 | 普通折叠和折叠组,用于展开或收起内容 | 普通折叠:bool变量 = EditorGUILayout.Foldout(bool变量, "标题名"); 折叠组: bool变量 = EditorGUILayout.BeginFoldoutHeaderGroup(bool变量, "标题名"); EditorGUILayout.EndFoldoutHeaderGroup(); |
间隔控件 | 在布局中添加间隔 | EditorGUILayout.Space(10); |
动画曲线控件 | 编辑动画曲线 | AnimationCurve变量 = EditorGUILayout.CurveField("动画曲线:", AnimationCurve变量); |
布局相关API | 水平、垂直布局和滚动视图布局 | 水平布局:EditorGUILayout.BeginHorizontal(); 一大堆控件 EditorGUILayout.EndHorizontal(); 垂直布局: EditorGUILayout.BeginVertical(); 一大堆控件 EditorGUILayout.EndVertical(); 滚动视图: Vector2布局 = EditorGUILayout.BeginScrollView(Vector2布局); 一大堆控件 EditorGUILayout.EndScrollView(); |
用于加载放置在Editor Default Resources
文件夹中的资源。
方法名 | 描述 | 示例代码 |
---|---|---|
EditorGUIUtility.Load(string path) |
根据指定路径加载资源,路径需包含后缀名。资源不存在时返回null |
var texture = EditorGUIUtility.Load("exampleTexture.png") as Texture2D; |
EditorGUIUtility.LoadRequired(string path) |
根据指定路径加载资源,路径需包含后缀名。资源不存在时直接报错 | var font = EditorGUIUtility.LoadRequired("exampleFont.ttf") as Font; |
Assets/Editor Default Resources/
文件夹下的相对路径。LoadRequired
方法时需确保资源存在,否则会中断程序并报错。作用:弹出搜索窗口选择资源,获取选择对象并监听选择事件。
方法名 | 描述 | 示例代码 |
---|---|---|
EditorGUIUtility.ShowObjectPicker |
显示对象选择器窗口。T为资源类型,obj为默认选中对象引用,allowSceneObjects决定是否允许选择场景对象,filter用于过滤对象名称,controlID一般设为0 | EditorGUIUtility.ShowObjectPicker |
EditorGUIUtility.GetObjectPickerObject() |
获取在对象选择器中选中的对象 | var selectedObj = EditorGUIUtility.GetObjectPickerObject(); |
Event.current |
获取当前发生的事件 | var currentEvent = Event.current; |
Event.current.commandName |
获取当前事件的命令名称 ObjectSelectorUpdated:对象选择发生变化时发送 ObjectSelectorClosed:对象选择窗口关闭时发送 |
var commandName = Event.current.commandName; |
EditorGUIUtility.PingObject(obj) ; |
对象选中提示,obj为需要选中的物体 | EditorGUIUtility.PingObject(img3); |
EditorGUIUtility.ShowObjectPicker
参数时,根据实际需求准确配置,如allowSceneObjects
影响可选择对象范围。Event.current.commandName
中的ObjectSelectorUpdated
(对象选择变化)和ObjectSelectorClosed
(选择窗口关闭)事件,实现对选择行为的响应。作用:实现窗口间事件传递,并在屏幕坐标系和GUI坐标系间进行坐标转换。
方法名 | 描述 | 示例代码 |
---|---|---|
EditorGUIUtility.CommandEvent(string commandName) |
发送指定名称的命令事件 | EditorGUIUtility.CommandEvent("SomeCustomCommand"); |
win.SendEvent(Event e) |
将事件发送到指定窗口。win为目标窗口,e为要发送的事件 | MyEditorWindow win = GetWindow |
Event.current.type |
判断当前事件的类型 | if(Event.current.type == EventType.ExecuteCommand) { /* 执行相关逻辑 */ } |
Event.current.commandName |
判断当前执行的事件命令名称 | if(Event.current.commandName == "SomeCustomCommand") { /* 执行相关逻辑 */ } |
EditorGUIUtility.GUIToScreenPoint(Vector2 guiPoint) |
将GUI坐标系中的点转换为屏幕坐标系中的点 | Vector2 screenPoint = EditorGUIUtility.GUIToScreenPoint(new Vector2(100, 100)); |
EditorGUIUtility.GUIToScreenRect(Rect guiRect) |
将GUI坐标系中的矩形转换为屏幕坐标系中的矩形 | Rect screenRect = EditorGUIUtility.GUIToScreenRect(new Rect(100, 100, 200, 200)); |
EditorGUIUtility.ScreenToGUIPoint(Vector2 screenPoint) |
将屏幕坐标系中的点转换为GUI坐标系中的点 | Vector2 guiPoint = EditorGUIUtility.ScreenToGUIPoint(new Vector2(500, 500)); |
EditorGUIUtility.ScreenToGUIRect(Rect screenRect) |
将屏幕坐标系中的矩形转换为GUI坐标系中的矩形 | Rect guiRect = EditorGUIUtility.ScreenToGUIRect(new Rect(500, 500, 300, 300)); |
作用:在指定区域设置特定的鼠标指针样式。
方法名 | 描述 | 示例代码 |
---|---|---|
EditorGUIUtility.AddCursorRect(Rect position, MouseCursor mouse) |
在指定矩形区域内设置鼠标指针样式。position为区域矩形,mouse为鼠标光标类型枚举值 | EditorGUIUtility.AddCursorRect(new Rect(0, 0, 100, 100), MouseCursor.Text); |
鼠标指针样式
MouseCursor
枚举包含多种光标类型,如Arrow
(箭头)、Text
(文本输入光标)、ResizeVertical
(垂直调整大小光标)等。
枚举值 | 描述 |
---|---|
Arrow |
普通指针箭头 |
Text |
文本文本光标 |
ResizeVertical |
调整大小垂直调整大小箭头 |
ResizeHorizontal |
调整大小水平调整大小箭头 |
Link |
带有链接徽章的链接箭头 |
SlideArrow |
滑动箭头带有小箭头的箭头,用于指示在数字字段处滑动 |
ResizeUpRight |
调整大小向上向右调整窗口边缘的大小 |
ResizeUpLeft |
调整大小向上向左调整窗口边缘的大小 |
MoveArrow |
带有移动符号的箭头,用于场景视图 |
RotateArrow |
旁边有用于场景视图的旋转符号的箭头 |
ScaleArrow |
旁边有用于场景视图的缩放符号的箭头 |
ArrowPlus |
旁边带有加号的箭头 |
ArrowMinus |
旁边带有减号的箭头 |
Pan |
用拖动的手拖动光标进行平移 |
Orbit |
用眼睛观察轨道的光标 |
Zoom |
使用放大镜进行缩放的光标 |
FPS |
带眼睛的光标和用于FPS导航的样式化箭头键 |
CustomCursor |
当前用户定义的光标 |
SplitResizeUpDown |
向上 - 向下调整窗口拆分器的大小箭头 |
SplitResizeLeftRight |
窗口拆分器的左 - 右调整大小箭头 |
作用:在指定区域绘制色板和曲线,辅助颜色和曲线相关的编辑展示。
方法名 | 描述 | 示例代码 |
---|---|---|
EditorGUIUtility.DrawColorSwatch(Rect rect, Color color) |
在指定矩形区域绘制色板。rect为绘制区域,color为要绘制的颜色 | EditorGUIUtility.DrawColorSwatch(new Rect(100, 100, 50, 50), Color.red); |
EditorGUIUtility.DrawCurveSwatch(Rect rect, AnimationCurve curve, SerializedProperty property, Color curveColor, Color backgroundColor) |
在指定矩形区域绘制曲线。rect为绘制范围,curve为动画曲线,property可为SerializedProperty 类型的曲线(可为null ),curveColor为曲线颜色,backgroundColor为背景颜色 |
AnimationCurve curve = new AnimationCurve(); curve.AddKey(0, 0); curve.AddKey(1, 1); EditorGUIUtility.DrawCurveSwatch(new Rect(200, 200, 100, 100), curve, null, Color.blue, Color.white); |
EditorGUILayout.ColorField
配合,为颜色选择提供直观展示。EditorGUILayout.CurveField
配合,用于动画曲线编辑场景的可视化辅助。获取选择对象的属性
属性 | 描述 | 示例代码 |
---|---|---|
Selection.activeObject |
获取当前在面板上选择的游戏物体 Object ,未选择则返回 Null ,选择多个则返回第一个选择的游戏物体 |
var obj = Selection.activeObject; |
Selection.activeGameObject |
获取当前在面板上选择的游戏物体 GameObject ,未选择或者选择的不是游戏对象则返回 Null ,选择多个则返回第一个选择的游戏物体 |
var go = Selection.activeGameObject; |
Selection.activeTransform |
获取当前在面板上选择的游戏物体的 Transform (只能获取 Hierarchy 窗口的对象),未选择则返回 Null ,选择多个则返回第一个选择的游戏物体 |
var trans = Selection.activeTransform; |
Selection.objects |
获取当前在面板上选择的物体数组,未选择则返回 Null |
var objs = Selection.objects; |
Selection.gameObjects |
获取当前选择的所有 GameObject ,未选择则返回 Null ,可遍历获取所有信息 |
var gos = Selection.gameObjects; |
Selection.transforms |
获取当前选择的所有 Transform ,未选择则返回 Null ,可遍历获取所有信息 |
var transs = Selection.transforms; |
常用静态方法
方法 | 描述 | 参数说明 | 示例代码 |
---|---|---|---|
Selection.Contains |
判断某个对象是否被选中(多选中存在也算) | obj :要判断的对象 |
Selection.Contains(obj); |
Selection.GetFiltered |
从当前选择对象中,筛选出想要的内容 | 类型 :要筛选的对象类型;筛选模式 :SelectionMode 枚举值,可通过位或 ` |
混用 |
Selection.selectionChanged(委托) |
当选中变化时会调用的委托 | 无 | Selection.selectionChanged += () => Debug.Log("Selection changed"); |
筛选模式
SelectionMode
枚举定义了不同的筛选模式,具体如下:
筛选模式 | 描述 |
---|---|
Unfiltered |
不过滤,返回所有选中对象。 |
TopLevel |
只获取最上层对象,子对象不获取。 |
Deep |
父对象和子对象都获取。 |
ExcludePrefab |
排除预设体。 |
Editable |
只选择可编辑的对象。 |
OnlyUserModifiable |
仅返回用户可修改的内容。 |
Assets |
只返回资源文件夹下的内容。 |
DeepAssets |
如果存在子文件夹,其中的内容也会获取。 |
若要同时使用多种筛选模式,可通过位或运算符|
来组合。
Selection.GetFiltered(SelectionMode.Unfiltered)
获取所有选中的GameObject
。Selection.GetFiltered(SelectionMode.DeepAssets)
获取资源文件夹及其子文件夹下所有选中的Texture2D
。Selection.GetFiltered(typeof(GameObject), SelectionMode.TopLevel | SelectionMode.Editable)
获取可编辑的最上层GameObject
,此处结合了TopLevel
和Editable
两种筛选模式。属性/方法 | 描述 | 示例代码 |
---|---|---|
Event.current |
获取当前正在处理的事件 | Event eventCurrent = Event.current; |
event.alt |
判断 Alt 键是否按下 |
if (eventCurrent.alt) Debug.Log("alt 键按下了"); |
event.shift |
判断 Shift 键是否按下 |
if (eventCurrent.shift) Debug.Log("shift 键按下了"); |
event.control |
判断 Ctrl 键是否按下 |
if (eventCurrent.control) Debug.Log("control 键按下了"); |
event.isMouse |
判断当前事件是否为鼠标事件 | if (eventCurrent.isMouse) { Debug.Log("鼠标相关事件"); } |
event.button |
若为鼠标事件,可获取鼠标按键(左、中、右) | if (eventCurrent.isMouse) { Debug.Log(eventCurrent.button); } |
event.mousePosition |
若为鼠标事件,可获取鼠标位置 | if (eventCurrent.isMouse) { Debug.Log("鼠标位置" + eventCurrent.mousePosition); } |
event.isKey |
判断当前事件是否为键盘事件 | if (eventCurrent.isKey) { Debug.Log("键盘相关事件"); } |
event.character |
若为键盘事件,可获取输入的字符 | if (eventCurrent.isKey) { Debug.Log(eventCurrent.character); } |
event.keyCode |
若为键盘事件,可获取对应的 KeyCode |
if (eventCurrent.isKey) { switch (eventCurrent.keyCode) { case KeyCode.Space: Debug.Log("空格键输入"); break; } } |
event.capsLock |
判断大小写锁定是否开启 | if (eventCurrent.capsLock) Debug.Log("大小写锁定开启"); else Debug.Log("大小写锁定关闭"); |
event.command |
判断 Windows 键或 Mac 的 Command 键是否按下 |
if (eventCurrent.command) Debug.Log("PC win 键按下 或 Mac Command 键按下"); |
event.commandName |
用于判断是否触发了特定的键盘事件,如复制、粘贴、剪切等 | if (eventCurrent.commandName == "Copy") { Debug.Log("按下了 ctrl + c"); } if (eventCurrent.commandName == "Paste") { Debug.Log("按下了 ctrl + v"); } if (eventCurrent.commandName == "Cut") { Debug.Log("按下了 ctrl + x"); } |
event.functionKey |
判断是否输入了功能键(如方向键、Page Up 、Page Down 等) |
if (eventCurrent.functionKey) Debug.Log("有功能按键输入"); |
event.numeric |
判断小键盘是否开启 | if (eventCurrent.numeric) Debug.Log("小键盘是否开启"); |
event.Use() |
在处理完当前事件后,阻止事件继续派发,避免与 Unity 其他编辑器事件逻辑冲突 | eventCurrent.Use(); |
通过这个特性[CustomEditor(typeof(TestInspectorMono))]
,我们就可以为TestInspectorMono脚本自定义Inspector窗口中的显示了
方法 | 参数 | 描述与用途 | 示例代码 |
---|---|---|---|
SerializedObject.FindProperty(string propertyPath) |
propertyPath :字符串类型,要查找的属性路径 |
在自定义编辑器脚本中,通过指定路径查找序列化对象中的属性,用于关联自定义脚本中的成员。 | SerializedObject so = new SerializedObject(target); SerializedProperty sp = so.FindProperty("myProperty"); |
SerializedProperty.FindPropertyRelative(string propertyName) |
propertyName :字符串类型,要查找的子属性名称 |
在自定义显示自定义数据结构类相关内容时,查找相对于当前属性的指定名称的子属性,方便获取子属性进行后续操作。 | SerializedProperty parentProp = serializedObject.FindProperty("parentProp"); SerializedProperty childProp = parentProp.FindPropertyRelative("childProp"); |
serializedObject.ApplyModifiedProperties() |
无 | 将对序列化属性所做的修改应用到目标对象上,在使用 SerializedProperty 修改属性值后,调用此方法可使修改生效。 | serializedObject.Update(); SerializedProperty prop = serializedObject.FindProperty("myProp"); prop.intValue = 10; serializedObject.ApplyModifiedProperties(); |
SerializedProperty.arraySize |
无 | 在处理数组或List属性自定义显示时,获取数组或List类型属性的容量,以便根据容量进行相关操作。 | SerializedProperty listProp = serializedObject.FindProperty("myList"); int size = listProp.arraySize; |
SerializedProperty.InsertArrayElementAtIndex(int index) |
index :整数类型,要插入元素的索引位置 |
在自定义显示数组或List时,为数组在指定索引位置插入默认元素,实现扩容操作,以满足自定义显示需求。 | SerializedProperty arrProp = serializedObject.FindProperty("myArray"); arrProp.InsertArrayElementAtIndex(2); |
SerializedProperty.DeleteArrayElementAtIndex(int index) |
index :整数类型,要删除元素的索引位置 |
在自定义显示数组或List时,删除数组中指定索引位置的元素,实现缩减容量操作,以满足自定义显示需求。 | SerializedProperty arrProp = serializedObject.FindProperty("myArray"); arrProp.DeleteArrayElementAtIndex(1); |
SerializedProperty.GetArrayElementAtIndex(int index) |
index :整数类型,要获取元素的索引位置 |
在自定义显示数组或List时,获取数组中指定索引位置的SerializedProperty 对象,用于对特定位置元素进行编辑或显示。 |
SerializedProperty arrProp = serializedObject.FindProperty("myArray"); SerializedProperty elementProp = arrProp.GetArrayElementAtIndex(0); |
EditorGUILayout.PropertyField(SerializedProperty property, GUIContent label) |
property :SerializedProperty 类型,要显示的属性对象;label :GUIContent 类型,属性的标题内容 |
在自定义Inspector窗口,按照属性类型自动处理控件绘制逻辑,显示指定的序列化属性,方便用户查看和编辑。 | SerializedProperty prop = serializedObject.FindProperty("myProp"); EditorGUILayout.PropertyField(prop, new GUIContent("My Prop")); |
OnInspectorGUI
函数内逻辑
public override void OnInspectorGUI()
{
if (GUILayout.Button("Click Me"))
{
Debug.Log("Button Clicked");
}
serializedObject.Update();
SerializedProperty prop = serializedObject.FindProperty("myProp");
EditorGUILayout.PropertyField(prop);
serializedObject.ApplyModifiedProperties();
}
ISerializationCallbackReceiver
接口
Dictionary
),通过在对象序列化和反序列化时执行自定义逻辑,实现对这些数据结构在Inspector窗口的间接编辑和显示。OnBeforeSerialize
:在对象被序列化之前调用。将对象中的数据转换为可序列化的形式,比如将Dictionary
数据存储到两个List
中,以便在Inspector窗口中显示和存储。OnAfterDeserialize
:在对象从磁盘反序列化后调用。将反序列化后的数据恢复到对象的原始数据结构中,比如从两个List
中读取数据填充到Dictionary
中。using UnityEngine;
using System;
using System.Collections.Generic;
public class MyClass : MonoBehaviour, ISerializationCallbackReceiver
{
public Dictionary<int, string> myDic = new Dictionary<int, string>();
[SerializeField] private List<int> keys = new List<int>();
[SerializeField] private List<string> values = new List<string>();
public void OnBeforeSerialize()
{
keys.Clear();
values.Clear();
foreach (var item in myDic)
{
keys.Add(item.Key);
values.Add(item.Value);
}
}
public void OnAfterDeserialize()
{
myDic.Clear();
for (int i = 0; i < keys.Count; i++)
{
myDic.Add(keys[i], values[i]);
}
}
}
方法 | 描述 | 示例代码 |
---|---|---|
Handles.Label(位置, 文本内容) |
在指定位置绘制文本 | Handles.Label(Vector3.zero, "示例文本"); |
Handles.DrawLine(起点, 终点, 粗细) |
在两点间绘制线段 | Handles.DrawLine(Vector3.zero, new Vector3(1, 0, 0), 2f); |
Handles.DrawDottedLine(起点, 终点, 粗细) |
在两点间绘制虚线 | Handles.DrawDottedLine(Vector3.zero, new Vector3(0, 0, 3), 3f); |
Handles.DrawWireArc(圆心, 法线, 绘制朝向, 角度, 半径) |
绘制线框弧线 | Handles.DrawWireArc(Vector3.zero, Vector3.up, Vector3.forward, 60, 4f); |
Handles.DrawSolidArc(圆心, 法线, 绘制朝向, 角度, 半径) |
绘制填充弧线 | Handles.DrawSolidArc(Vector3.zero, Vector3.up, Vector3.right, 45, 3f); |
Handles.DrawSolidDisc(圆心, 法线, 半径) |
绘制填充圆 | Handles.DrawSolidDisc(Vector3.zero, Vector3.up, 2.5f); |
Handles.DrawWireDisc(圆心, 法线, 半径) |
绘制线框圆 | Handles.DrawWireDisc(Vector3.zero, Vector3.up, 3.5f); |
Handles.DrawWireCube(中心点, xyz大小) |
绘制立方体线框 | Handles.DrawWireCube(Vector3.zero, new Vector3(1, 1, 1)); |
Handles.DrawAAConvexPolygon(几何体各顶点) |
绘制几何体 | Handles.DrawAAConvexPolygon(Vector3.zero, Vector3.right, new Vector3(1, 1, 0)); |
Handles.DoPositionHandle(位置, 角度) |
显示并处理移动轴控制柄 | Vector3 newPosition = Handles.DoPositionHandle(Vector3.zero, Quaternion.identity); |
Handles.PositionHandle(位置, 角度) |
显示并处理移动轴控制柄 | Vector3 newPosition = Handles.PositionHandle(Vector3.zero, Quaternion.identity); |
Handles.DoRotationHandle(角度, 位置) |
显示并处理旋转轴控制柄 | Quaternion newRotation = Handles.DoRotationHandle(Quaternion.identity, Vector3.zero); |
Handles.RotationHandle(角度, 位置) |
显示并处理旋转轴控制柄 | Quaternion newRotation = Handles.RotationHandle(Quaternion.identity, Vector3.zero); |
Handles.DoScaleHandle(缩放, 位置, 角度, HandleUtility.GetHandleSize(位置)) |
显示并处理缩放轴控制柄 | Vector3 newScale = Handles.DoScaleHandle(new Vector3(1, 1, 1), Vector3.zero, Quaternion.identity, HandleUtility.GetHandleSize(Vector3.zero)); |
Handles.ScaleHandle(缩放, 位置, 角度, HandleUtility.GetHandleSize(位置)) |
显示并处理缩放轴控制柄 | Vector3 newScale = Handles.ScaleHandle(new Vector3(1, 1, 1), Vector3.zero, Quaternion.identity, HandleUtility.GetHandleSize(Vector3.zero)); |
Handles.FreeMoveHandle(位置, 句柄大小, 移动步进值, 渲染控制手柄的回调函数) |
显示自由移动控制柄 | Vector3 newFreePosition = Handles.FreeMoveHandle(Vector3.zero, 1f, new Vector3(0.1f, 0.1f, 0.1f), Handles.RectangleHandleCap); |
Handles.FreeRotateHandle(角度, 位置, 句柄大小) |
显示自由旋转控制柄 | Quaternion newFreeRotation = Handles.FreeRotateHandle(Quaternion.identity, Vector3.zero, 1f); |
Handles.BeginGUI() |
开始在 Scene 视图中绘制 GUI | Handles.BeginGUI(); |
Handles.EndGUI() |
结束在 Scene 视图中绘制 GUI | Handles.EndGUI(); |
HandleUtility.GetHandleSize(Vector3 position) |
获取在场景中给定位置的句柄的合适尺寸 | float handleSize = HandleUtility.GetHandleSize(Vector3.zero); |
HandleUtility.WorldToGUIPoint(Vector3 worldPosition) |
将世界坐标转换为 GUI 坐标 | Vector2 guiPos = HandleUtility.WorldToGUIPoint(Vector3.zero); |
HandleUtility.GUIPointToWorldRay(Vector2 position) |
将屏幕上的像素坐标转换为射线 | Ray ray = HandleUtility.GUIPointToWorldRay(new Vector2(0, 0)); |
HandleUtility.DistanceToLine(Vector3 lineStart, Vector3 lineEnd) |
计算场景中一条线段与鼠标光标的最短距离 | float dis = HandleUtility.DistanceToLine(Vector3.zero, new Vector3(1, 0, 0)); |
HandleUtility.PickGameObject(Vector2 position, bool isSelecting) |
在编辑器中根据鼠标位置进行对象的拾取 | GameObject pickedObj = HandleUtility.PickGameObject(new Vector2(0, 0), true); |
类 | 静态参数 | 描述 |
---|---|---|
Handles |
color |
在调用 Handles 中的绘制 API 之前,可设置此颜色属性来指定绘制图形的颜色,如 Handles.color = new Color(0, 1, 0, 1f); 可将后续绘制的图形颜色设为绿色 |
方法 | 描述 | 示例代码 |
---|---|---|
Gizmos.DrawCube(中心点, 大小) |
绘制实心立方体 | Gizmos.DrawCube(Vector3.zero, Vector3.one); |
Gizmos.DrawWireCube(中心点, 大小) |
绘制立方体线框 | Gizmos.DrawWireCube(this.transform.position, new Vector3(2, 1, 3)); |
Gizmos.DrawFrustum(绘制中心, FOV角度, 远裁切平面, 近裁切平面, 屏幕长宽比) |
绘制视锥 | Gizmos.DrawFrustum(this.transform.position, 30, 50, 0.5f, 1.7f); |
Gizmos.DrawSphere(中心点, 半径) |
绘制实心球体 | Gizmos.DrawSphere(this.transform.position, 2); |
Gizmos.DrawWireSphere(中心点, 半径) |
绘制球体线框 | Gizmos.DrawWireSphere(this.transform.position, 3); |
Gizmos.DrawWireMesh(mesh, 位置, 角度) |
绘制网格线 | if (mesh != null) Gizmos.DrawWireMesh(mesh, this.transform.position, this.transform.rotation); |
Gizmos.DrawGUITexture(new Rect(x, y, w, h), 图片信息) |
绘制贴图 | if (pic != null) Gizmos.DrawGUITexture(new Rect(this.transform.position.x, this.transform.position.y, 160, 90), pic); |
Gizmos.DrawIcon(Vector3位置, “图标名”) |
绘制图标,图标需放在Assets/Gizmos/文件夹中 | Gizmos.DrawIcon(this.transform.position, "MyIcon"); |
Gizmos.DrawLine(起点, 终点) |
绘制线段 | Gizmos.DrawLine(this.transform.position, this.transform.position + Vector3.one); |
Gizmos.DrawMesh(mesh, 位置, 角度) |
绘制网格 | if (mesh != null) Gizmos.DrawMesh(mesh, this.transform.position, this.transform.rotation); |
Gizmos.DrawRay(起点, 方向) |
绘制射线 | Gizmos.DrawRay(this.transform.position, this.transform.forward); |
类 | 静态参数 | 描述 | 示例代码 |
---|---|---|---|
Gizmos |
color |
修改 Gizmos 绘制图形的颜色 | Gizmos.color = Color.green; |
Gizmos |
matrix |
修改 Gizmos 绘制前的矩阵,可改变绘制内容的角度、位置和缩放,使用 Matrix4x4.identity 可还原矩阵 |
Gizmos.matrix = Matrix4x4.TRS(this.transform.position, this.transform.rotation, Vector3.one); Gizmos.matrix = Matrix4x4.identity; |
每帧调用,绘制的内容随时可在 Scene 窗口中看见
private void OnDrawGizmos()
{
Debug.Log("Gizmos");
}
仅当脚本依附的 GameObject 被选中时才会每帧调用绘制相关内容 |
private void OnDrawGizmosSelected()
{
Debug.Log("Gizmos2");
}
方法 | 描述 | 返回值 | 示例代码 |
---|---|---|---|
EditorUtility.DisplayDialog |
显示含确定按钮的提示窗口,阻塞逻辑 | bool |
if (EditorUtility.DisplayDialog("标题", "信息", "确定")) Debug.Log("点击确定"); |
EditorUtility.DisplayDialogComplex |
显示三按钮提示面板,阻塞逻辑 | int |
int res = EditorUtility.DisplayDialogComplex("标题", "信息", "按钮1", "按钮2", "按钮3"); |
EditorUtility.DisplayProgressBar |
显示进度条,不阻塞逻辑 | void |
EditorUtility.DisplayProgressBar("进度条", "信息", 0.5f); |
EditorUtility.ClearProgressBar |
关闭进度条 | void |
EditorUtility.ClearProgressBar(); |
EditorUtility.SaveFilePanel |
显示文件存储面板 | string |
string path = EditorUtility.SaveFilePanel("标题", "", "文件名", "后缀"); |
EditorUtility.SaveFilePanelInProject |
显示项目内文件存储面板 | string |
string path = EditorUtility.SaveFilePanelInProject("标题", "文件名", "后缀", "摘要"); |
EditorUtility.SaveFolderPanel |
显示文件夹存储面板 | string |
string path = EditorUtility.SaveFolderPanel("标题", "", "默认名"); |
EditorUtility.OpenFilePanel |
显示打开文件面板 | string |
string path = EditorUtility.OpenFilePanel("标题", "", "后缀"); |
EditorUtility.OpenFolderPanel |
显示打开文件夹面板 | string |
string path = EditorUtility.OpenFolderPanel("标题", "", "默认名"); |
EditorUtility.CompressTexture |
压缩纹理到指定格式 | void |
EditorUtility.CompressTexture(texture, format, quality); |
EditorUtility.CollectDependencies |
查找对象依赖资源列表 | object[] |
object[] deps = EditorUtility.CollectDependencies(new Object[] { obj }); |
DisplayDialog
和 DisplayDialogComplex
会阻塞逻辑,需处理窗口后继续执行。DisplayProgressBar
不阻塞逻辑,但要配合 ClearProgressBar
使用。方法 | 描述 | 示例代码 |
---|---|---|
AssetDatabase.CreateAsset(资源, 路径) |
在指定路径创建资源,路径从 Assets/ 开始,不能在 StreamingAssets 中创建,不能创建预设体,资源为要创建的资源对象,路径需包含后缀 |
Material mat = new Material(Shader.Find("Specular")); AssetDatabase.CreateAsset(mat, "Assets/Resources/MyMaterial.mat"); |
AssetDatabase.CreateFolder(父文件夹, 新文件夹名) |
在指定父文件夹下创建新文件夹,路径从 Assets/ 开始,父文件夹为父文件夹路径,新文件夹名为要创建的文件夹名称 |
AssetDatabase.CreateFolder("Assets/Resources", "MyTestFolder"); |
AssetDatabase.CopyAsset(源资源, 目标路径) |
拷贝资源到指定目标路径,路径从 Assets/ 开始,需写后缀名,源资源为源资源的路径,目标路径为目标资源的保存路径 |
AssetDatabase.CopyAsset("Assets/Editor Default Resources/head.png", "Assets/Resources/MyTestFolder/head.png"); |
AssetDatabase.MoveAsset(老路径, 新路径) |
将资源从老路径移动到新路径,路径从 Assets/ 开始,老路径为资源原来的路径,新路径为资源要移动到的路径 |
AssetDatabase.MoveAsset("Assets/Resources/MyTestFolder/head.png", "Assets/Resources/head.png"); |
AssetDatabase.DeleteAsset(资源路径) |
删除指定路径的资源,路径从 Assets/ 开始,资源路径为要删除的资源的路径 |
AssetDatabase.DeleteAsset("Assets/Resources/head.png"); |
AssetDatabase.DeleteAssets(路径数组, 失败路径列表) |
批量删除资源,路径从 Assets/ 开始,路径数组为要删除的资源路径数组,失败路径列表用于存储删除失败的路径列表 |
List |
AssetDatabase.GetAssetPath(资源) |
获取指定资源的路径,可配合 Selection 选中资源使用,资源为要获取路径的资源对象 |
Debug.Log(AssetDatabase.GetAssetPath(Selection.activeObject)); |
AssetDatabase.LoadAssetAtPath<资源类型>(资源路径) |
根据指定路径加载资源,路径从 Assets/ 开始,仅在编辑器下使用,资源路径为要加载的资源的路径 |
Texture txt = AssetDatabase.LoadAssetAtPath |
AssetDatabase.Refresh() |
对资源进行移动、导入、删除等操作后,执行刷新操作,以便在 Project 窗口中正确显示 |
AssetDatabase.Refresh(); |
AssetDatabase.GetImplicitAssetBundleName(资源路径) |
返回指定资源所属的 AB 包名,路径从 Assets/ 开始,资源路径为要查询的资源的路径 |
string abName = AssetDatabase.GetImplicitAssetBundleName("Assets/Resources/head.png"); |
方法 | 描述 | 示例代码 |
---|---|---|
PrefabUtility.SaveAsPrefabAsset(GameObject对象, 路径) |
动态创建预设体,路径从 Assets/ 开始,需包含 .prefab 后缀,GameObject对象为要保存为预制体的游戏对象 |
GameObject go = new GameObject(); PrefabUtility.SaveAsPrefabAsset(go, "Assets/MyPrefab.prefab"); |
PrefabUtility.LoadPrefabContents(路径) |
加载预制体到内存,路径从 Assets/ 开始,加载的预制体可用于修改,需与 UnloadPrefabContents 配对使用 |
GameObject prefab = PrefabUtility.LoadPrefabContents("Assets/MyPrefab.prefab"); |
PrefabUtility.UnloadPrefabContents(GameObject对象) |
释放通过 LoadPrefabContents 加载到内存中的预制体,GameObject对象为要释放的预制体对象 |
PrefabUtility.UnloadPrefabContents(prefab); (假设 prefab 已加载) |
PrefabUtility.SavePrefabAsset(预设体对象, out bool 是否保存成功) |
修改并保存已有预设体,预设体对象为要修改保存的预制体,是否保存成功为输出参数,用于指示保存操作是否成功 | GameObject prefab = AssetDatabase.LoadAssetAtPath |
PrefabUtility.InstantiatePrefab(Object对象) |
实例化预设体,Object对象为要实例化的预制体对象 | GameObject prefab = AssetDatabase.LoadAssetAtPath |
方法 | 描述 | 示例代码 |
---|---|---|
EditorApplication.update |
每帧更新事件,可在编辑器执行逻辑,需添加和移除回调 | EditorApplication.update += () => { if (EditorApplication.isPlaying) Debug.Log("播放中"); }; |
EditorApplication.hierarchyChanged |
层级视图变化时触发,需添加和移除回调 | EditorApplication.hierarchyChanged += () => Debug.Log("层级视图改变"); |
EditorApplication.projectChanged |
项目资源变化时触发,需添加和移除回调 | EditorApplication.projectChanged += () => Debug.Log("项目资源改变"); |
EditorApplication.playModeStateChanged |
编辑器播放状态改变时触发,需添加和移除回调 | EditorApplication.playModeStateChanged += () => Debug.Log("播放状态改变"); |
EditorApplication.pauseStateChanged |
编辑器暂停状态改变时触发,需添加和移除回调 | EditorApplication.pauseStateChanged += () => Debug.Log("暂停状态改变"); |
EditorApplication.applicationContentsPath |
获取 Unity 安装目录 Data 路径 | Debug.Log(EditorApplication.applicationContentsPath); |
EditorApplication.applicationPath |
获取 Unity 安装目录可执行程序路径 | Debug.Log(EditorApplication.applicationPath); |
EditorApplication.EnterPlaymode() |
使编辑器进入播放模式 | EditorApplication.EnterPlaymode(); |
EditorApplication.ExitPlaymode() |
使编辑器退出播放模式 | EditorApplication.ExitPlaymode(); |
CompilationPipeline
是Unity编辑器中的一个公共类,主要用于处理与代码编译相关的操作和事件。最常用的功能是判断代码是否编译结束,例如在动态生成脚本的情况下,只有在编译结束后才能使用新脚本。
创建自定义面板代码
using UnityEditor;
public class MyCompilationPipelineLearnWindow : EditorWindow
{
[MenuItem("编辑器拓展教程/MyCompilationPipelineLearnWindow")]
private static void OpenLesson46()
{
MyCompilationPipelineLearnWindow win =
EditorWindow.GetWindow<MyCompilationPipelineLearnWindow>("CompilationPipeline知识点学习");
win.Show();
}
}
常用内容
在继承EditorWindow
的类中,通过以下方式监听编译相关事件:
private void OnEnable()
{
// 当一个程序集编译结束会主动调用该回调函数
// 传入参数:string arg1(编译完成的程序集名)、CompilerMessage[] arg2(编译完成后产生的编译消息数组,包括编译警告和错误信息)
CompilationPipeline.assemblyCompilationFinished += CompilationPipeline_assemblyCompilationFinished;
// 当所有程序集编译结束会主动调用该回调函数
// 传入参数:object obj(ActiveBuildStatus 活动生成状态对象)
CompilationPipeline.compilationFinished += CompilationPipeline_compilationFinished;
}
private void CompilationPipeline_compilationFinished(object obj)
{
Debug.Log("所有程序集编译结束");
}
private void CompilationPipeline_assemblyCompilationFinished(string arg1, CompilerMessage[] arg2)
{
Debug.Log("程序集名:" + arg1);
}
private void OnDestroy()
{
CompilationPipeline.assemblyCompilationFinished -= CompilationPipeline_assemblyCompilationFinished;
CompilationPipeline.compilationFinished -= CompilationPipeline_compilationFinished;
}
注意事项
CompilationPipeline
的assemblyCompilationFinished
和compilationFinished
这两个事件,在添加回调函数后,要记得在合适的时机(比如脚本销毁时)移除回调函数,避免出现内存泄漏以及不必要的逻辑执行问题。CompilationPipeline
类的这些功能仅在Unity编辑器环境中有效,在游戏打包后的运行环境中无法使用。AssetImporter
和AssetPostprocessor
需配合使用,主要用于资源导入批量设置和资源导入后处理。
AssetPostprocessor
(资源后处理器类)用于处理资源导入时的通用逻辑。可通过继承该类并实现回调方法自定义处理资源,常进行某种类型资源的通用设置和统一批量处理。
常用属性
AssetImporter assetImporter
:对应类型的资源导入器对象string assetPath
:导入资源的路径常用回调方法
OnPreprocessTexture()
:导入纹理资源前调用,可修改导入设置OnPostprocessTexture(Texture2D texture)
:导入纹理资源后调用,可进行后处理OnPreprocessModel()
:导入模型资源前调用,可修改导入设置OnPostprocessModel(GameObject obj)
:导入模型资源后调用,可进行后处理OnPreprocessAudio()
:导入音频资源前调用,可修改导入设置OnPostprocessAudio(AudioClip clip)
:导入音频资源后调用,可进行后处理AssetImporter
(资源导入器类)是特定资源类型的资源导入程序的基类,提供配置和管理资源导入设置的方法和属性。一般使用其子类设置导入资源的相关信息。
子类
TextureImporter
:用于导入纹理资源并配置设置ModelImporter
:用于导入模型资源并配置设置AudioImporter
:用于导入音频资源并配置设置VideoClipImporter
:用于导入视频资源并配置设置ScriptedImporter
:用于创建自定义资源导入器联动使用示例
public class MyAssetPostprocessor : AssetPostprocessor
{
// 纹理相关
void OnPreprocessTexture()
{
Debug.Log("纹理设置回调" + assetPath);
TextureImporter improter = assetImporter as TextureImporter;
improter.textureType = TextureImporterType.Sprite;
improter.mipmapEnabled = false;
}
void OnPostprocessTexture(Texture2D texture)
{
Debug.Log("纹理后处理回调" + texture.name);
EditorUtility.CompressTexture(texture, TextureFormat.ETC_RGB4, TextureCompressionQuality.Fast);
}
// 模型相关
void OnPreprocessModel()
{
ModelImporter improter = assetImporter as ModelImporter;
// 可修改模型导入设置
}
void OnPostprocessModel(GameObject obj)
{
// 可进行模型后处理
}
// 音频相关
void OnPreprocessAudio()
{
AudioImporter improter = assetImporter as AudioImporter;
// 可修改音频导入设置
}
void OnPostprocessAudio(AudioClip clip)
{
// 可进行音频后处理
}
}