unity製作prefab的時候,有的時候可能需要hold住導入操作來做一點事情,這裏提供兩種思路來處理;
下面這個例子,是爲了設置Animator的cullingmode;
方案一:修改prefab的文本
而修改了.prefab的文件,然後保存;
using UnityEngine;
using UnityEditor;
using System.Text.RegularExpressions;
using System.IO;
class MyAllPostprocessor : AssetPostprocessor
{
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
foreach (string str in importedAssets)
{
Regex prefabSuffix = new Regex(".prefab$");
string absolutePath = Application.dataPath + str.Replace("Assets", "");
if (prefabSuffix.IsMatch(str)){
ResetTxt(absolutePath);
}
}
}
static void ResetTxt(string path){
StreamReader sr = new StreamReader(path);
string str = sr.ReadToEnd();
sr.Close();
string pattern = @"m_CullingMode: \d";
Regex prefabSuffix = new Regex(pattern);
if(prefabSuffix.IsMatch(str)){
str = prefabSuffix.Replace(str, "m_CullingMode: 2");
}
StreamWriter sw = new StreamWriter(path, false);
sw.WriteLine(str);
sw.Close();
}
}
方案二:使用PrefabUtility
using UnityEngine;
using UnityEditor;
using System.Text.RegularExpressions;
using System.IO;
class MyAllPostprocessor : AssetPostprocessor
{
static void OnPostprocessAllAssets(string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths)
{
foreach (string str in importedAssets)
{
Regex prefabSuffix = new Regex(".prefab$");
string absolutePath = Application.dataPath + str.Replace("Assets", "");
if (prefabSuffix.IsMatch(str)){
ResetAnimator(str);
}
}
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
static void ResetAnimator(string path){
GameObject obj = AssetDatabase.LoadAssetAtPath<GameObject>(path);
bool hit = false;
var newPrefab = PrefabUtility.InstantiatePrefab(obj) as GameObject;
Animator[] animators = newPrefab.GetComponentsInChildren<Animator>(true);
for (int i = 0; i < animators.Length; i++)
{
var animator = animators[i];
if(animator.cullingMode != AnimatorCullingMode.CullCompletely)
{
hit = true;
animator.cullingMode = AnimatorCullingMode.CullCompletely;
}
}
if (hit)
{
PrefabUtility.SaveAsPrefabAsset(newPrefab, path);
GameObject.DestroyImmediate(newPrefab);
return;
}
GameObject.DestroyImmediate(newPrefab);
return;
}
}
擴展:使用MenuItem對選中prefab進行操作
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class ArtPrefabMenu
{
[MenuItem("Tools/設置CullingMode爲CullingCompletely")]
public static void SetPrefabCullingMode()
{
List<string> prefabPathList = new List<string>();
for(int i = 0; i < Selection.assetGUIDs.Length; i++){
string path = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[i]);
prefabPathList.Add(path);
}
ArtToolUtil.CheckFuncWithProgress<UnityEngine.GameObject>(prefabPathList.ToArray(), "檢查Prefab的Animator", (string path, UnityEngine.GameObject rootGo) =>
{
bool hit = false;
var newPrefab = PrefabUtility.InstantiatePrefab(rootGo) as GameObject;
Animator[] animators = newPrefab.GetComponentsInChildren<Animator>(true);
for (int i = 0; i < animators.Length; i++)
{
var animator = animators[i];
if(animator.cullingMode != AnimatorCullingMode.CullCompletely)
{
hit = true;
animator.cullingMode = AnimatorCullingMode.CullCompletely;
}
}
if (hit)
{
PrefabUtility.SaveAsPrefabAsset(newPrefab, path);
GameObject.DestroyImmediate(newPrefab);
return string.Format("path==>{0}", path);
}
GameObject.DestroyImmediate(newPrefab);
return null;
});
AssetDatabase.SaveAssets();
AssetDatabase.Refresh();
}
}