文章目录
- [1 AssetDatabase](#1 AssetDatabase)
-
- [1.1 准备工作](#1.1 准备工作)
- [1.2 常用 API](#1.2 常用 API)
- [2 PrefabUtility](#2 PrefabUtility)
-
- [1 准备工作](#1 准备工作)
- [2 常用 API](#2 常用 API)
- [3 EditorApplication](#3 EditorApplication)
-
- [3.1 准备工作](#3.1 准备工作)
- [3.2 常用 API](#3.2 常用 API)
- [4 CompilationPipeline](#4 CompilationPipeline)
-
- [4.1 CompilationPipeline.assemblyCompilationFinished](#4.1 CompilationPipeline.assemblyCompilationFinished)
- [4.2 CompilationPipeline.compilationFinished](#4.2 CompilationPipeline.compilationFinished)
- [4.3 示例](#4.3 示例)
- [5 AssetPostprocessor](#5 AssetPostprocessor)
-
- [5.1 常用 API](#5.1 常用 API)
- [5.2 示例](#5.2 示例)
- [6 AssetImporter](#6 AssetImporter)
1 AssetDatabase
AssetDatabase 是 Unity 引擎中的一个编辑器类,用于在编辑器环境中管理和操作项目中的资源(Assets)。
它提供一系列静态方法,使得开发者能够在编辑器脚本中进行资源的创建、拷贝、移动、删除等操作。
在编辑器相关处都可以使用 AssetDatabase,但它属于编辑器功能,无法被打包出去,只能在 Unity 编辑器中使用。
1.1 准备工作
AssetDatabase 可以在任何编辑器功能开发时使用,但为了讲解方便,这里通过一个自定义窗口来进行讲解。
csharp
using UnityEditor;
using UnityEngine;
public class Lesson42Window : EditorWindow
{
[MenuItem("Unity 编辑器拓展/Lesson42/AssetDatabase 知识讲解")]
public static void Open() {
Lesson42Window win = GetWindow<Lesson42Window>();
win.Show();
}
private void OnGUI() { }
}
1.2 常用 API
- 创建资源
csharp
public static extern void CreateAsset(UnityEngine.Object asset, string path);
// 示例:
private void OnGUI() {
if (GUILayout.Button("创建资源")) {
var mat = new Material(Shader.Find("Legacy Shaders/Specular"));
AssetDatabase.CreateAsset(mat, "Assets/Resources/MyMaterial.mat");
}
}
- 路径从 Assets/... 开始,且文件夹必须存在。
- 不能在 StreamingAssets 中创建资源。
- 不能创建预设体(需使用 PrefabUtility 创建)。
- 只能创建资源相关,例如材质球等。
- 路径需要写后缀。
- 创建文件夹
csharp
public static extern string CreateFolder(string parentFolder, string newFolderName);
// 示例:
private void OnGUI() {
if (GUILayout.Button("创建文件夹")) {
AssetDatabase.CreateFolder("Assets/Resources", "MyFolder");
}
}
- 路径从 Assets/... 开始。
- 路径需要写后缀。
- 拷贝资源
csharp
public static extern bool CopyAsset(string path, string newPath);
// 示例:
private void OnGUI() {
if (GUILayout.Button("拷贝资源")) {
AssetDatabase.CopyAsset("Assets/Resources/MyMaterial.mat", "Assets/Resources/newMaterial.mat");
}
}
- 路径从 Assets/... 开始。
- 路径需要写后缀。
- 移动资源
csharp
public static extern bool DeleteAsset(string path);
public static bool DeleteAssets(string[] paths, List<string> outFailedPaths);
// 示例:
private void OnGUI() {
if (GUILayout.Button("删除资源")) {
AssetDatabase.DeleteAsset("Assets/Resources/newMaterial2.mat");
}
}
- 路径从 Assets/... 开始。
- 路径需要写后缀。
- 目标资源不存在不会报错。
- 获取资源路径
csharp
public static extern string GetAssetPath(UnityEngine.Object assetObject);
// 示例:
private void OnGUI() {
if (GUILayout.Button("获取资源路径")) {
Debug.Log(AssetDatabase.GetAssetPath(Selection.activeObject));
}
}
- 可以配合 Selection 选中资源一起使用。
- 加载资源
csharp
public static T LoadAssetAtPath<T>(string assetPath) where T : UnityEngine.Object;
public static extern UnityEngine.Object[] LoadAllAssetsAtPath(string assetPath);
// 示例:
private void OnGUI() {
if (GUILayout.Button("加载资源")) {
var mat = AssetDatabase.LoadAssetAtPath<Material>("Assets/Resources/newMaterial.mat");
Debug.Log(mat.name);
}
}
-
路径从 Assets/... 开始。
-
路径需要写后缀。
-
LoadAllAssetsAtPath 一般可以用来加载图集资源,返回值为 Object 数据。
如果是图集,第一个为图集本身,之后的便是图集中的所有 Sprite。
- 刷新
csharp
public static void Refresh();
- AssetDatabase 的 API 内部会自动调用刷新。使用其他操作时需要手动刷新。
- 获取资源 AB 包名称
csharp
public static extern string GetImplicitAssetBundleName(string assetPath);
- 路径从 Assets/... 开始。
更多内容:https://docs.unity3d.com/ScriptReference/AssetDatabase.html
2 PrefabUtility
PrefabUtility 是 Unity 编辑器中的一个公共类,提供一些用于处理 Prefab(预制体或称预设体)的方法。
主要功能包括:实例化预制体、创建预制体、修改预制体等等。
1 准备工作
csharp
using UnityEditor;
using UnityEngine;
public class Lesson44Window : EditorWindow
{
[MenuItem("Unity 编辑器拓展/Lesson44/PrefabUtility 知识讲解")]
public static void Open() {
Lesson44Window win = GetWindow<Lesson44Window>();
win.Show();
}
private void OnGUI() { }
}
2 常用 API
- 创建预设体
csharp
public static GameObject SaveAsPrefabAsset(GameObject instanceRoot, string assetPath);
// 示例:
private void OnGUI() {
if (GUILayout.Button("动态创建预设体")) {
GameObject obj = new GameObject();
obj.AddComponent<Rigidbody>();
obj.AddComponent<BoxCollider>();
PrefabUtility.SaveAsPrefabAsset(obj, "Assets/Resources/TestObj.prefab");
DestroyImmediate(obj); // 立即删除 obj
}
}
- 加载预制体
csharp
public static GameObject LoadPrefabContents(string assetPath);
public static void UnloadPrefabContents(GameObject contentsRoot);
// 示例:
private void OnGUI() {
if (GUILayout.Button("加载预制体对象")) {
GameObject testObj = PrefabUtility.LoadPrefabContents("Assets/Resources/TestObj.prefab");
testObj.AddComponent<MeshRenderer>();
PrefabUtility.SaveAsPrefabAsset(testObj, "Assets/Resources/TestObj.prefab"); // 需要新建预制体保存
PrefabUtility.UnloadPrefabContents(testObj);
}
}
- 加载到内存中,不能用来实例化,一般加载出来进行修改。
- 该方法的加载其实已经实例化了预设体,但该实例化对象并在 Scene 窗口中,而是在一个看不见的独立的场景中。
- 可以进行脚本移除,子对象创建等操作。
- 两个方法需要配对使用,加载了就要释放。
- 修改预设体
csharp
public static GameObject SavePrefabAsset(GameObject asset);
public static GameObject SavePrefabAsset(GameObject asset, out bool savedSuccessfully);
// 示例:
private void OnGUI() {
if (GUILayout.Button("修改已有预设体")) {
GameObject testObj = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Resources/TestObj.prefab");
testObj.AddComponent<BoxCollider>();
PrefabUtility.SavePrefabAsset(testObj);
}
}
- 该方法不能存储实例化后的内容,只能存储对应的预设体对象。
- 实例化预制体
csharp
public static UnityEngine.Object InstantiatePrefab(UnityEngine.Object assetComponentOrGameObject);
// 示例:
private void OnGUI() {
if (GUILayout.Button("实例化预设体")) {
GameObject testObj = AssetDatabase.LoadAssetAtPath<GameObject>("Assets/Resources/TestObj.prefab");
PrefabUtility.InstantiatePrefab(testObj);
}
}
更多内容:https://docs.unity3d.com/2022.3/Documentation/ScriptReference/PrefabUtility.html
3 EditorApplication
EditorApplication 是 Unity 编辑器中的一个公共类,主要提供和编辑器本身相关的一些功能。
例如,编辑器事件监听(播放、暂停等)、生命周期判断(是否运行中、暂停中、编译中)、编辑器进入播放模式、退出播放模式等等。
3.1 准备工作
csharp
using UnityEditor;
using UnityEngine;
public class Lesson45Window : EditorWindow
{
[MenuItem("Unity 编辑器拓展/Lesson45/EditorApplication 知识讲解")]
public static void Open() {
Lesson45Window win = GetWindow<Lesson45Window>();
win.Show();
}
private void OnEnable() {
// 添加监听事件
EditorApplication.update += ...;
}
private void OnDestroy() {
// 移除监听事件
EditorApplication.update -= ...;
}
}
3.2 常用 API
-
监听编辑器事件
- EditorApplication.update:每帧更新事件,可以用于在编辑器中执行一些逻辑。
- EditorApplication.hierarchyChanged:层级视图变化事件,当场景中的对象发生变化时触发。
- EditorApplication.projectChanged:项目变化事件,当项目中的资源发生变化时触发。
- EditorApplication.playModeStateChanged:编辑器播放状态变化时触发。
- EditorApplication.pauseStateChanged:编辑器暂停状态变化时触发。
-
管理编辑器生命周期相关
- EditorApplication.isPlaying:判断当前是否处于游戏运行状态。
- EditorApplication.isPaused:判断当前游戏是否处于暂停状态。
- EditorApplication.isCompiling:判断 Unity 编辑器是否正在编译代码。
- EditorApplication.isUpdating:判断 Unity 编辑器是否正在刷新 AssetDatabase。
-
获取 Unity 应用程序路径相关
- EditorApplication.applicationContentsPath:Unity 安装目录 Data 路径。
- EditorApplication.applicationPath:Unity 安装目录可执行程序路径。
-
常用方法
- EditorApplication.Exit(0):退出 Unity 编辑器。
- EditorApplication.ExitPlaymode():退出播放模式,切换到编辑模式。
- EditorApplication.EnterPlaymode():进入播放模式。
更多内容:
4 CompilationPipeline
CompilationPipeline 是 Unity 编辑器中的一个公共类,用于处理代码编译相关的操作和事件,通常使用它得知代码是否编译结束。
比如动态生成脚本时,需要在编译结束后才能使用新的脚本。
4.1 CompilationPipeline.assemblyCompilationFinished
- 命名空间:UnityEditor.Compilation;
- 主要作用:当一个程序集编译结束会主动调用该回调函数。
- 参数:
- string arg1:编译完成的程序集名。
- CompilerMessage[] arg2:编译完成后产生的编译消息数组,包括编译警告和错误信息。
4.2 CompilationPipeline.compilationFinished
- 命名空间:UnityEditor.Compilation;
- 主要作用:当所有程序集编译结束会主动调用该回调函数。
- 参数:
- object obj:ActiveBuildStatus 活动生成状态对象。
4.3 示例
csharp
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;
public class Lesson46Window : EditorWindow
{
[MenuItem("Unity 编辑器拓展/Lesson46/CompilationPipeline 知识讲解")]
public static void Open() {
Lesson46Window win = GetWindow<Lesson46Window>();
win.Show();
}
private void OnEnable() {
CompilationPipeline.assemblyCompilationFinished += CompilationPipeline_assemblyCompilationFinished;
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;
}
}
更多内容:https://docs.unity3d.com/ScriptReference/Compilation.CompilationPipeline.html
5 AssetPostprocessor
AssetPostprocessor(资源后处理器)主要用于处理资源导入时的通用逻辑,可以通过继承该类并实现其中的一些回调方法来自定义处理资源。
一般会进行以下处理:
- 进行某种类型资源的通用设置。
- 对某种类型资源进行统一批量的处理。
5.1 常用 API
-
常用属性:
- AssetImporter assetImporter:对应类型的资源导入器对象。
- string assetPath:导入资源的路径。
-
常用回调方法:
- void OnPreprocessTexture():导入纹理资源之前调用,允许修改纹理的导入设置。
- void OnPostprocessTexture(Texture2D texture):导入纹理资源之后调用,允许对导入后为其进行后处理,例如修改纹理格式、尺寸、压缩等等。
- void OnPreprocessModel():导入模型资源之前调用,允许修改纹理的导入设置。
- void OnPostprocessModel(GameObject obj):导入模型资源之后调用,允许对导入后为其进行后处理,例如修改网格、材质、动画等。
- void OnPreprocessAudio():导入音频资源之前调用,允许修改纹理的导入设置。
- void OnPostprocessAudio(AudioClip clip):导入音频资源之后调用,允许对导入后为其进行后处理,例如修改音频格式、质量等。
- 等等
注意:如果只想对某种资源中的某些内容进行处理,可以自己加命名规则。
更多内容:https://docs.unity3d.com/ScriptReference/AssetPostprocessor.html
5.2 示例
csharp
using UnityEditor;
using UnityEngine;
public class Lesson47 : AssetPostprocessor
{
void OnPreprocessTexture() { }
void OnPostprocessTexture(Texture2D texture) {
Debug.Log("纹理后处理回调" + texture.name);
// 设置压缩格式
EditorUtility.CompressTexture(texture, TextureFormat.ETC_RGB4, TextureCompressionQuality.Fast);
}
void OnPreprocessModel() { }
void OnPostprocessModel(GameObject obj) { }
void OnPreprocessAudio() { }
void OnPostprocessAudio(AudioClip clip) { }
}
6 AssetImporter
AssetImporter(资源导入器)是特定资源类型的资源导入程序的基类,用于配置和管理资源的导入设置。
一般不会直接使用该类,而是通过使用继承它的子类来设置导入资源的相关信息。
当我们导入一个资源时,在 Inspector 窗口中进行的相关设置都是通过继承该类的子类实现的。
分类:
- TextureImporter:纹理导入器。
- ModelImporter:模型导入器。
- AudioImporter:音频导入器。
- VideoClipImporter:视频导入器。
- ScriptedImporter:自定义的资源导入器,对特定格式的资源进行自定义配置处理。
使用示例:
csharp
using UnityEditor;
using UnityEngine;
public class Lesson47 : AssetPostprocessor
{
void OnPreprocessTexture() {
Debug.Log("纹理设置回调" + assetPath);
// 进行导入设置
TextureImporter importer = (TextureImporter) assetImporter; // TextureImporter
importer.textureType = TextureImporterType.Sprite;
importer.mipmapEnabled = false;
}
void OnPostprocessTexture(Texture2D texture) { }
void OnPreprocessModel() {
TextureImporter importer = (ModelImporter) assetImporter; // ModelImporter
}
void OnPostprocessModel(GameObject obj) { }
void OnPreprocessAudio() {
TextureImporter importer = (AudioImporter) assetImporter; // AudioImporter
}
void OnPostprocessAudio(AudioClip clip) { }
}
更多内容:
- TextureImporter:https://docs.unity3d.com/ScriptReference/TextureImporter.html
- ModelImporter:https://docs.unity3d.com/ScriptReference/ModelImporter.html
- AudioImporter:https://docs.unity3d.com/ScriptReference/AudioImporter.html
- VideoClipImporter:https://docs.unity3d.com/ScriptReference/VideoClipImporter.html
- ScriptedImporter:https://docs.unity3d.com/ScriptReference/AssetImporters.ScriptedImporter.html