Unity编辑器扩展快速回顾
知识点来源:总结人间自有韬哥在, 唐老狮,豆包
目录
- 1.自定义菜单栏拓展
- 1.1.Editor文件夹用途
- 1.2.添加自定义页签
- 1.3.Component菜单加脚本
- 1.4.Inspector脚本右键菜单
- 1.5.快捷键设置
- 2.自定义窗口扩展
- 2.1.创建窗口类
- 2.2显示窗口
- 2.3.窗口事件回调函数
- 2.4.窗口中常用的生命周期函数
- 2.5.编辑器窗口类中的常用成员
- 3.EditorGUI
- 3.1. EditorWindow 类成员
- 3.2. EditorGUILayout 相关功能
- 4.EditorGUIUtility
- 4.1 资源加载
- 4.2 搜索框查询对象选中提示
- 4.3 窗口事件传递坐标转换
- 4.4 指定区域使用对应鼠标指针
- 4.5 绘制色板绘制曲线
- 5.Selection
- 6.Event
- 7.Inspector窗口拓展
- 7.1.方法和参数
- 7.2.重写
- 7.3.接口
- 8.Handles
- 8.1.方法
- 8.2. 静态参数
- 9.Gizmos
- 9.1.方法
- 9.2. 静态参数
- 9.3. 响应函数
- 10.EditorUtility
- 11.AssetDatabase
- 12.PrefabUtility
- 13.EditorApplication
- 14.CompilationPipeline
- 15.AssetImporter和AssetPostprocessor
- 15.1.AssetPostprocessor
- 15.2.AssetImporter
1.自定义菜单栏拓展
1.1.Editor文件夹用途
Unity中,Editor为特殊文件夹,使用UnityEditor命名空间的脚本需放此,避免打包报错。
1.2.添加自定义页签
菜单栏
- 命名空间:UnityEditor
- 特性:MenuItem
- 用法:
[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"); }
1.3.Component菜单加脚本
- 命名空间:UnityEngine
- 特性:AddComponentMenu
- 用法:
[AddComponentMenu("选项")]
修饰继承MonoBehaviour的脚本 - 例:
[AddComponentMenu("教程/Lesson02")] public class Lesson02 : MonoBehaviour {}
1.4.Inspector脚本右键菜单
- 用法:
[MenuItem("CONTEXT/脚本名/页签/选项")]
- 例:
[MenuItem("CONTEXT/Lesson02/教程/TestFun4")] static void TestFun4() { Debug.Log("TestFun4"); }
1.5.快捷键设置
单键:路径后加 “ _ 按键”;组合键:用 %
(ctrl)、#
(shift)、&
(alt)
- 例:
[MenuItem("教程/TestFun5 _F4")] static void TestFun5() { Debug.Log("TestFun5"); }
2.自定义窗口扩展
2.1.创建窗口类
在 UnityEditor
命名空间下,我们通过创建一个继承自 EditorWindow
的类来实现自定义窗口。例如:
using UnityEditor;
public class Lesson03_自定义窗口拓展 : EditorWindow
{
private void OnGUI()
{
GUILayout.Label("测试文本");
if (GUILayout.Button("测试按钮"))
{
Debug.Log("Test");
}
}
}
2.2显示窗口
我们可以使用添加自定义页签的方式来开启窗口,这需要通过调用 EditorWindow.GetWindow
方法来创建窗口对象。该方法有多种重载形式,主要参数包括:
- Type 或 T:指定窗口类的类型。
- utility:若为
true
,可创建浮动实用程序窗口(这种窗口可自由拖动和改变大小);若为false
,则创建正常窗口。 - title:用于设置窗口标题。
- focus:决定是否为窗口提供焦点(若窗口已存在),新创建的窗口始终会获得焦点。
- desiredDockNextTo:表示窗口试图停靠到其上的
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();
}
// 其他代码...
}
2.3.窗口事件回调函数
继承 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("当选中对象发生变化时"); } |
2.4.窗口中常用的生命周期函数
生命周期函数 | 触发时机 | 用途 | 示例代码 |
---|---|---|---|
OnEnable() | 窗口被激活时调用,通常在窗口创建时执行一次,用于进行初始化工作,如注册事件监听器或设置初始变量。 | 进行初始化操作 | private void OnEnable() { // 初始化操作 } |
OnGUI() | 每帧都会调用,用于绘制编辑器窗口的 GUI,使用 GUILayout 或 EditorGUILayout 等类创建界面元素。 | 绘制界面相关元素 | private void OnGUI() { // 绘制界面元素 } |
OnDestroy() | 窗口被销毁时调用,如关闭编辑器或切换场景时触发,用于进行最终的清理工作,释放未释放的资源。 | 执行清理操作 | private void OnDestroy() { // 清理操作 } |
Update() | 编辑器窗口每帧更新时调用,用于执行每帧需要进行的逻辑。 | 处理每帧相关逻辑 | private void Update() { // 每帧逻辑 } |
2.5.编辑器窗口类中的常用成员
静态变量
静态变量 | 描述 | 示例代码 |
---|---|---|
focusedWindow | 当前已获得键盘焦点的 EditorWindow (只读)。 | EditorWindow currentFocusedWindow = EditorWindow.focusedWindow; |
mouseOverWindow | 当前在鼠标光标下的 EditorWindow (只读)。 | EditorWindow currentMouseOverWindow = EditorWindow.mouseOverWindow; |
静态函数
静态函数 | 描述 | 示例代码 |
---|---|---|
CreateWindow | 创建窗口,可用于创建非单例唯一的窗口。 | Lesson03_自定义窗口拓展 newWindow = EditorWindow.CreateWindow<Lesson03_自定义窗口拓展>(); |
GetWindow | 创建单例唯一的窗口对象。 | Lesson03_自定义窗口拓展 singletonWindow = EditorWindow.GetWindow<Lesson03_自定义窗口拓展>(); |
GetWindowWithRect | 返回一个指定位置、大小的窗口。 | Rect rect = new Rect(100, 100, 200, 200); Lesson03_自定义窗口拓展 sizedWindow = EditorWindow.GetWindowWithRect<Lesson03_自定义窗口拓展>(rect); |
HasOpenInstances | 检查编辑器窗口是否打开。 | bool isOpen = EditorWindow.HasOpenInstances<Lesson03_自定义窗口拓展>(); |
成员变量
成员变量 | 描述 | 示例代码 |
---|---|---|
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(); |
3.EditorGUI
3.1. EditorWindow 类成员
静态变量
变量名 | 描述 | 示例代码 |
---|---|---|
focusedWindow | 当前获得键盘焦点的 EditorWindow (只读) | EditorWindow currentFocusedWindow = EditorWindow.focusedWindow; |
mouseOverWindow | 当前鼠标光标下的 EditorWindow (只读) | EditorWindow currentMouseOverWindow = EditorWindow.mouseOverWindow; |
静态函数
函数名 | 描述 | 示例代码 |
---|---|---|
CreateWindow | 创建非单例唯一的窗口 | Lesson03_自定义窗口拓展 newWindow = EditorWindow.CreateWindow<Lesson03_自定义窗口拓展>(); |
GetWindow | 创建单例唯一的窗口对象 | Lesson03_自定义窗口拓展 singletonWindow = EditorWindow.GetWindow<Lesson03_自定义窗口拓展>(); |
GetWindowWithRect | 返回指定位置、大小的窗口 | Rect rect = new Rect(100, 100, 200, 200); Lesson03_自定义窗口拓展 sizedWindow = EditorWindow.GetWindowWithRect<Lesson03_自定义窗口拓展>(rect); |
HasOpenInstances | 检查编辑器窗口是否打开 | bool isOpen = EditorWindow.HasOpenInstances<Lesson03_自定义窗口拓展>(); |
成员变量
变量名 | 描述 | 示例代码 |
---|---|---|
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(); |
3.2. EditorGUILayout 相关功能
布局选项
类型 | 描述 | 示例代码 |
---|---|---|
固定宽高 | 设置控件固定宽度和高度 | 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(); |
4.EditorGUIUtility
4.1 资源加载
用于加载放置在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
方法时需确保资源存在,否则会中断程序并报错。
- 资源路径必须是
4.2 搜索框查询对象选中提示
作用:弹出搜索窗口选择资源,获取选择对象并监听选择事件。
方法名 | 描述 | 示例代码 |
---|---|---|
EditorGUIUtility.ShowObjectPicker<T>(UnityEngine.Object obj, bool allowSceneObjects, string filter, int controlID) | 显示对象选择器窗口。T为资源类型,obj为默认选中对象引用,allowSceneObjects决定是否允许选择场景对象,filter用于过滤对象名称,controlID一般设为0 | EditorGUIUtility.ShowObjectPicker<GameObject>(null, false, "", 0); |
EditorGUIUtility.GetObjectPickerObject() | 获取在对象选择器中选中的对象 | var selectedObj = EditorGUIUtility.GetObjectPickerObject(); |
Event.current | 获取当前发生的事件 | var currentEvent = Event.current; |
Event.current.commandName | 获取当前事件的命令名称 ObjectSelectorUpdated:对象选择发生变化时发送 ObjectSelectorClosed:对象选择窗口关闭时发送 | var commandName = Event.current.commandName;<br>if (Event.current.commandName == "ObjectSelectorUpdated"){ // 当选择发生更新时通知进入}<br>else if (Event.current.commandName == "ObjectSelectorClosed"){ // 当选择窗口关闭时通知进入} |
EditorGUIUtility.PingObject(obj) ; | 对象选中提示,obj为需要选中的物体 | EditorGUIUtility.PingObject(img3); |
- 注意事项
- 设置
EditorGUIUtility.ShowObjectPicker
参数时,根据实际需求准确配置,如allowSceneObjects
影响可选择对象范围。 - 通过监听
Event.current.commandName
中的ObjectSelectorUpdated
(对象选择变化)和ObjectSelectorClosed
(选择窗口关闭)事件,实现对选择行为的响应。
- 设置
4.3 窗口事件传递坐标转换
作用:实现窗口间事件传递,并在屏幕坐标系和GUI坐标系间进行坐标转换。
方法名 | 描述 | 示例代码 |
---|---|---|
EditorGUIUtility.CommandEvent(string commandName) | 发送指定名称的命令事件 | EditorGUIUtility.CommandEvent("SomeCustomCommand"); |
win.SendEvent(Event e) | 将事件发送到指定窗口。win为目标窗口,e为要发送的事件 | MyEditorWindow win = GetWindow<MyEditorWindow>(); win.SendEvent(Event.current); |
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)); |
- 注意事项
- 事件传递会自动打开目标窗口并转移焦点。
- 进行坐标转换时,若在布局函数中,需考虑布局偏移对坐标的影响,且多显示器环境下坐标计算会涉及多个显示器。
4.4 指定区域使用对应鼠标指针
作用:在指定区域设置特定的鼠标指针样式。
方法名 | 描述 | 示例代码 |
---|---|---|
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 | 窗口拆分器的左 - 右调整大小箭头 |
4.5 绘制色板绘制曲线
作用:在指定区域绘制色板和曲线,辅助颜色和曲线相关的编辑展示。
方法名 | 描述 | 示例代码 |
---|---|---|
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
配合,用于动画曲线编辑场景的可视化辅助。
- 绘制色板常与
5.Selection
获取选择对象的属性
属性 | 描述 | 示例代码 |
---|---|---|
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 | 如果存在子文件夹,其中的内容也会获取。 |
若要同时使用多种筛选模式,可通过位或运算符|
来组合。
- 示例 1:运用
Selection.GetFiltered<GameObject>(SelectionMode.Unfiltered)
获取所有选中的GameObject
。 - 示例 2:使用
Selection.GetFiltered<Texture2D>(SelectionMode.DeepAssets)
获取资源文件夹及其子文件夹下所有选中的Texture2D
。 - 示例 3:通过
Selection.GetFiltered(typeof(GameObject), SelectionMode.TopLevel | SelectionMode.Editable)
获取可编辑的最上层GameObject
,此处结合了TopLevel
和Editable
两种筛选模式。
6.Event
属性/方法 | 描述 | 示例代码 |
---|---|---|
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(); |
7.Inspector窗口拓展
通过这个特性[CustomEditor(typeof(TestInspectorMono))]
,我们就可以为TestInspectorMono脚本自定义Inspector窗口中的显示了
7.1.方法和参数
方法 | 参数 | 描述与用途 | 示例代码 |
---|---|---|---|
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")); |
7.2.重写
OnInspectorGUI
函数内逻辑
- 描述与用途:在该函数内部处理各种绘制和交互逻辑,根据不同的用户操作(如按钮点击)和状态变化(如属性值改变)进行相应处理,实现Inspector窗口的定制化交互和显示。
- 示例代码:
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();
}
7.3.接口
ISerializationCallbackReceiver
接口
- 描述与用途:用于处理不被Unity默认支持在Inspector窗口显示的数据结构(如
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]);
}
}
}
8.Handles
8.1.方法
方法 | 描述 | 示例代码 |
---|---|---|
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); |
8.2. 静态参数
类 | 静态参数 | 描述 |
---|---|---|
Handles | color | 在调用 Handles 中的绘制 API 之前,可设置此颜色属性来指定绘制图形的颜色,如 Handles.color = new Color(0, 1, 0, 1f); 可将后续绘制的图形颜色设为绿色 |
9.Gizmos
9.1.方法
方法 | 描述 | 示例代码 |
---|---|---|
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); |
9.2. 静态参数
类 | 静态参数 | 描述 | 示例代码 |
---|---|---|---|
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; |
9.3. 响应函数
每帧调用,绘制的内容随时可在 Scene 窗口中看见
private void OnDrawGizmos()
{
Debug.Log("Gizmos");
}
仅当脚本依附的 GameObject 被选中时才会每帧调用绘制相关内容 |
private void OnDrawGizmosSelected()
{
Debug.Log("Gizmos2");
}
10.EditorUtility
方法 | 描述 | 返回值 | 示例代码 |
---|---|---|---|
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
使用。
11.AssetDatabase
方法 | 描述 | 示例代码 |
---|---|---|
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<string> failList = new List<string>(); AssetDatabase.DeleteAssets(new string[] { "Assets/Resources/head.png", "Assets/Resources/head2.png" }, failList); |
AssetDatabase.GetAssetPath(资源) | 获取指定资源的路径,可配合 Selection 选中资源使用,资源为要获取路径的资源对象 | Debug.Log(AssetDatabase.GetAssetPath(Selection.activeObject)); |
AssetDatabase.LoadAssetAtPath<资源类型>(资源路径) | 根据指定路径加载资源,路径从 Assets/ 开始,仅在编辑器下使用,资源路径为要加载的资源的路径 | Texture txt = AssetDatabase.LoadAssetAtPath<Texture>("Assets/Resources/head.png"); |
AssetDatabase.Refresh() | 对资源进行移动、导入、删除等操作后,执行刷新操作,以便在 Project 窗口中正确显示 | AssetDatabase.Refresh(); |
AssetDatabase.GetImplicitAssetBundleName(资源路径) | 返回指定资源所属的 AB 包名,路径从 Assets/ 开始,资源路径为要查询的资源的路径 | string abName = AssetDatabase.GetImplicitAssetBundleName("Assets/Resources/head.png"); |
12.PrefabUtility
方法 | 描述 | 示例代码 |
---|---|---|
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<GameObject>("Assets/MyPrefab.prefab"); bool success; PrefabUtility.SavePrefabAsset(prefab, out success); |
PrefabUtility.InstantiatePrefab(Object对象) | 实例化预设体,Object对象为要实例化的预制体对象 | GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/MyPrefab.prefab"); PrefabUtility.InstantiatePrefab(prefab); |
13.EditorApplication
方法 | 描述 | 示例代码 |
---|---|---|
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(); |
14.CompilationPipeline
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编辑器环境中有效,在游戏打包后的运行环境中无法使用。
15.AssetImporter和AssetPostprocessor
AssetImporter
和AssetPostprocessor
需配合使用,主要用于资源导入批量设置和资源导入后处理。
15.1.AssetPostprocessor
AssetPostprocessor
(资源后处理器类)用于处理资源导入时的通用逻辑。可通过继承该类并实现回调方法自定义处理资源,常进行某种类型资源的通用设置和统一批量处理。
常用属性
AssetImporter assetImporter
:对应类型的资源导入器对象string assetPath
:导入资源的路径
常用回调方法
- 纹理相关
OnPreprocessTexture()
:导入纹理资源前调用,可修改导入设置OnPostprocessTexture(Texture2D texture)
:导入纹理资源后调用,可进行后处理
- 模型相关
OnPreprocessModel()
:导入模型资源前调用,可修改导入设置OnPostprocessModel(GameObject obj)
:导入模型资源后调用,可进行后处理
- 音频相关
OnPreprocessAudio()
:导入音频资源前调用,可修改导入设置OnPostprocessAudio(AudioClip clip)
:导入音频资源后调用,可进行后处理
15.2.AssetImporter
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)
{
// 可进行音频后处理
}
}