在新开发一个UI模块的时候,往往需要连带的创建包括Script、Prefab、Atlas等一系列的文件和目录。这些文件的目录结构、命名格式往往都比较统一,所以我们可以编写自定义程序一键生成,即可以快速高效的创建文件,也避免了手动创建过程中可以出现的命名不规范、单词拼写错误、目录路径创建错误等不必要的小麻烦。
using UnityEngine;
using UnityEditor;
using System.IO;
using System.Text;
public class GenerateScript : EditorWindow
{
[MenuItem("EditorTools/GenerateScript")]
public static void ShowCustomEditorWindow()
{
string directoryPath = Application.dataPath + "/Script";
if (!Directory.Exists(directoryPath))
Directory.CreateDirectory(directoryPath);
string filePath = directoryPath + "/Script.cs";
FileStream fileStream = File.Create(filePath);
string content = @"
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CustomScript : MonoBehaviour
{
public void Start()
{
}
}
";
byte[] byteArray = Encoding.UTF8.GetBytes(content);
fileStream.Write(byteArray, 0, byteArray.Length);
fileStream.Close();
AssetDatabase.Refresh();
}
}
创建Script主要使用的是C#中的File类,本质就是用File类创建一个后缀名为.cs的文本文件。
上面是一个简单的示例,在项目工程Script目录下创建了一个Script.cs脚本。
Directory类用于创建文件目录,File.Create创建FileStream类,FileStream类负责具体的文件写入操作。这里需要注意的是content的编写,content所编写的内容就是最后生成的.cs文件中的代码。为了方便多行编写,这里使用了@符号。
相关文档连接:
Directory类文档连接:https://learn.microsoft.com/zh-cn/dotnet/api/system.io.directory?view=net-7.0
File类文档连接:https://learn.microsoft.com/zh-cn/dotnet/api/system.io.file?view=net-7.0
FileStream类文档连接:https://learn.microsoft.com/zh-cn/dotnet/api/system.io.filestream?view=net-7.0
using System;
using System.Reflection;
using UnityEngine;
using UnityEditor;
public class GeneratePrefab : EditorWindow
{
[MenuItem("EditorTools/GeneratePrefab")]
public static void ShowCustomEditorWindow()
{
if (!EditorApplication.isCompiling)
GeneratePrefabAsyn();
}
[UnityEditor.Callbacks.DidReloadScripts]
private static void GeneratePrefabAsyn()
{
Assembly assembly = AppDomain.CurrentDomain.Load("Assembly-CSharp");
Type type = assembly.GetType("CustomScript");
if (type != null)
{
GameObject instanceGameObject = new GameObject("CustomPrefab");
Component component = instanceGameObject.AddComponent(type);
PrefabUtility.SaveAsPrefabAsset(instanceGameObject, "Assets/CustomPrefab.prefab");
GameObject.DestroyImmediate(instanceGameObject, true);
}
}
}
这一部分是自动创建Prefab,并绑定之前自动创建的Script。
这里有两个坑是需要特别注意的。
第一个是项目脚本中的类是在Assembly-CSharp程序集下的,而编辑器脚本中的类是在Assembly-CSharp-Editor程序集下的。所以需要先通过AppDomain.CurrentDomain.Load("Assembly-CSharp")方法获取Assembly-CSharp程序集,然后在通过assembly.GetType("CustomScript")方法获取类型。
第二个是当新创建Script时Unity会重新编译Assembly-CSharp程序集,所以在Prefab上绑定新的Script需要等待Unity把程序集编译完成。EditorApplication.isCompiling可以判断当前编辑器是否在编译脚本。[UnityEditor.Callbacks.DidReloadScripts] 则用于指定Script加载完成后的回调,需要注意的是回调必须是静态方法。
最后的话则是使用 PrefabUtility.SaveAsPrefabAsset 方法将创建的Prefab保存到指定路径。
相关文档连接:
Assembly文档连接:https://learn.microsoft.com/zh-cn/dotnet/api/system.reflection.assembly?view=net-7.0
DidReloadScripts文档连接:https://docs.unity3d.com/cn/2022.2/ScriptReference/Callbacks.DidReloadScripts.html
PrefabUtility文档连接:https://docs.unity3d.com/cn/2022.2/ScriptReference/PrefabUtility.html
using UnityEngine;
using UnityEngine.U2D;
using UnityEditor;
using UnityEditor.U2D;
using System.IO;
public class GenerateScript : EditorWindow
{
[MenuItem("EditorTools/GenerateSpriteAtlas")]
public static void ShowCustomEditorWindow()
{
string directoryPath = Application.dataPath + "/SpriteAtlas";
if (!Directory.Exists(directoryPath))
Directory.CreateDirectory(directoryPath);
SpriteAtlas spriteAtlas = new SpriteAtlas();
SpriteAtlasPackingSettings packSetting = new SpriteAtlasPackingSettings()
{
blockOffset = 1,
enableRotation = false,
enableTightPacking = false,
padding = 4,
};
spriteAtlas.SetPackingSettings(packSetting);
string localPath = directoryPath + "/SpriteAtlasName.spriteatlas";
AssetDatabase.CreateAsset(spriteAtlas, localPath);
AssetDatabase.Refresh();
}
}
首先还是使用new SpriteAtlas方法来创建对象。对于SpriteAtlas对象的参数设置需要用到SpriteAtlasPackingSettings类,上面的示例只进行了简单设置,更多参数设置可以查阅文档。参数设置完成之后通过AssetDatabase.CreateAsset方法保存SpriteAtlas对象。
SpriteAtlas文档连接:https://docs.unity3d.com/cn/2022.2/ScriptReference/U2D.SpriteAtlas.html
SpriteAtlasPackingSettings文档连接:https://docs.unity3d.com/cn/2022.2/ScriptReference/U2D.SpriteAtlasPackingSettings.html