using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditorInternal;
// 美術在導出模型時,有很多掛點是沒有用的。但有些掛點卻是有用的,跟美術溝通,有用掛點的名字。
// 再使用該腳本進行一健清理
public class BatchAnimatorOptimize
{
// 指定要檢查的文件夾
private static string[] checkDirs = {
//"Assets/Game/Actors",
//"Assets/Game/Actors/Wing/8001",
//"Assets/Game/Actors/Mount/7004"
};
private static string[] searchPatterns = new string[] {
"buff_.*",
"hurt_.*",
"_.*point",
"ui",
"guadian",
};
[MenuItem("自定義工具/優化動畫(去掉無用節點)")]
public static void Process()
{
Debug.Log("開始批量處理");
string[] guids = AssetDatabase.FindAssets("t:prefab", checkDirs);
foreach (var guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);
if (null == prefab.GetComponent<Animator>()
|| null == prefab.GetComponentInChildren<SkinnedMeshRenderer>())
{
continue;
}
if (null != prefab.GetComponent<Animator>()
&& null != prefab.transform.Find("GameObject")
&& prefab.transform.childCount <= 3)
{
Debug.Log("處理有BuG的:" + path);
// ProcessForBug(prefab);
}
else
{
Debug.Log("處理無BuG的:" + path);
ProcessCollect(prefab);
}
}
AssetDatabase.SaveAssets();
Debug.Log("處理完成");
}
private static void ProcessForBug(GameObject prefab)
{
GameObject prefab_obj = GameObject.Instantiate(prefab);
GameObject temp_gameobj = prefab_obj.transform.Find("GameObject").gameObject;
temp_gameobj.transform.SetParent(prefab_obj.transform.parent, true);
Animator animator = prefab_obj.GetComponent<Animator>();
ComponentUtility.CopyComponent(animator);
ComponentUtility.PasteComponentAsNew(temp_gameobj);
GameObject.DestroyImmediate(animator);
string[] exposed_transforms = new string[] { };
SearchExposed(temp_gameobj.transform, ref exposed_transforms);
if (exposed_transforms.Length > 0)
{
AnimatorUtility.OptimizeTransformHierarchy(temp_gameobj, exposed_transforms);
}
temp_gameobj.transform.SetParent(prefab_obj.transform, true);
PrefabUtility.ReplacePrefab(prefab_obj, prefab);
GameObject.DestroyImmediate(prefab_obj);
}
private static void ProcessCollect(GameObject prefab)
{
string[] exposed_transforms = new string[] { };
SearchExposed(prefab.transform, ref exposed_transforms);
if (exposed_transforms.Length > 0)
{
AnimatorUtility.OptimizeTransformHierarchy(prefab, exposed_transforms);
}
PrefabUtility.ResetToPrefabState(prefab);
PrefabUtility.SetPropertyModifications(prefab, new PropertyModification[] { });
}
private static void SearchExposed(Transform root, ref string[] exposedTransforms)
{
var pathStack = new List<string>();
for (int i = 0; i < searchPatterns.Length; ++i)
{
if (string.IsNullOrEmpty(searchPatterns[i]))
{
continue;
}
var regex = new Regex(searchPatterns[i]);
SearchExposed(pathStack, root, regex, ref exposedTransforms);
pathStack.Clear();
}
}
private static void SearchExposed(List<string> pathStack, Transform transform, System.Text.RegularExpressions.Regex regex, ref string[] exposedTransforms)
{
pathStack.Add(transform.name);
var pathBuilder = new StringBuilder();
for (int i = 0; i < pathStack.Count; ++i)
{
pathBuilder.Append(pathStack[i]);
if (i < pathStack.Count - 1)
{
pathBuilder.Append('/');
}
}
var path = pathBuilder.ToString();
if (regex.IsMatch(path))
{
AddExposedTransform(path, ref exposedTransforms);
}
foreach (Transform child in transform)
{
SearchExposed(pathStack, child, regex, ref exposedTransforms);
}
pathStack.RemoveAt(pathStack.Count - 1);
}
private static void AddExposedTransform(string value, ref string[] exposedTransforms)
{
foreach (var stringValue in exposedTransforms)
{
if (stringValue == value)
{
return;
}
}
ArrayUtility.Add(ref exposedTransforms, value);
}
}