下面实现的一个功能是对一个文件夹下的所有prefab批量修改,比如移除某个子物体,添加一个组件等,然后保存到另一个新的文件夹下;
如下,我们实现一个扩展窗口,用于选择源文件夹和目标文件夹;然后遍历所有的prefab,进行修改,然后保存到新文件夹下,在保存之前检查资源是否存在,如果已存在,就移除再保存新的;
首先,在unity内加载资源时用的是工程的相对路径,而对于C#的IO来说,需要用绝对路径,那么先提供一组相对路径和绝对路径之间的转换接口,如下所示,这里使用了正则替换,注意模式字符串要用@前缀标记为原义;
public static string GetRelativePath(string path){
string srcPath = path.Replace("\\", "/");
var retPath = Regex.Replace(srcPath, @"\b.*Assets", "Assets");
return retPath;
}
public static string GetAbsolutePath(string path){
string srcPath = path.Replace("\\", "/");
var retPath = Regex.Replace(srcPath, @"\b.*Assets", Application.dataPath);
return retPath;
}
然后就是简单的编辑器扩展功能,这里要使用PrefabUtility来进行prefab的保存,而不能使用AssetDatabase的接口;
using UnityEngine;
using UnityEditor;
using System.IO;
public class ArtActorPrefabModifyWindow : EditorWindow
{
public static string assetSrcFolderPath = Application.dataPath + "/Resources/Prefabs/FashionPartPrefab";
public static string assetDstFolderPath = "Assets/Resources/Prefabs/FashionPartPrefabNew";
[MenuItem ("====Tools====/Prefab/移除时装部件内的骨骼")]
public static void ShowWindow () {
EditorWindow thisWindow = EditorWindow.GetWindow(typeof(ArtActorPrefabModifyWindow));
thisWindow.titleContent = new GUIContent("骨骼移除");
thisWindow.position = new Rect(Screen.width/2, Screen.height/2, 600, 800);
}
void OnGUI()
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("选择源文件夹");
EditorGUILayout.TextField(assetSrcFolderPath);
if (GUILayout.Button("选择"))
{
assetSrcFolderPath = EditorUtility.OpenFolderPanel("选择文件夹", assetSrcFolderPath, "");
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("选择源文件夹");
EditorGUILayout.TextField(assetDstFolderPath);
if (GUILayout.Button("选择"))
{
assetDstFolderPath = EditorUtility.OpenFolderPanel("选择文件夹", assetDstFolderPath, "");
}
EditorGUILayout.EndHorizontal();
if (GUILayout.Button("开始提取") && assetSrcFolderPath != null && assetDstFolderPath != null)
{
Seperate();
}
}
private static void Seperate(){
assetSrcFolderPath = PathUtil.GetAbsolutePath(assetSrcFolderPath);
var files = Directory.GetFiles(assetSrcFolderPath, "*.prefab");
string dstPath = PathUtil.GetRelativePath(assetDstFolderPath);
foreach (var file in files)
{
string srcPath = PathUtil.GetRelativePath(file);
GameObject srcObj = AssetDatabase.LoadAssetAtPath(srcPath, typeof(GameObject)) as GameObject;
if (srcObj == null)
continue;
GameObject dstObj = AssetDatabase.LoadAssetAtPath(dstPath, typeof(GameObject)) as GameObject;
if (dstObj != null)
AssetDatabase.DeleteAsset(dstPath);
dstObj = GameObject.Instantiate(srcObj);
Transform avatar = dstObj.transform.Find("Bip001");
if (avatar != null) {
GameObject.DestroyImmediate(avatar.gameObject);
PrefabUtility.SaveAsPrefabAsset(dstObj, dstPath + "/" + srcObj.name + ".prefab");
}
GameObject.DestroyImmediate(dstObj);
}
}
}