最近爲美術編寫一個Unity編輯器的擴展,主要爲了減輕美術在修改預製對象時的機械化操做的繁瑣和出錯。具體實現的幾個功能:html
一、刪除指定組件;編輯器
二、複製、粘貼指定的組件;動畫
三、從新關聯新的屬性;spa
四、從新保存預製對象;3d
1、刪除指定類型的組件code
public static void RemoveComponentHandler(GameObject gameObject, Type componentType) { foreach (var component in gameObject.GetComponents<Component>()) { if (component.GetType() == componentType) { GameObject.DestroyImmediate(component); } } }
2、複製組件(這裏實現的是一次僅複製一個某類型的組件)component
public static void CopyComponentHandler(Type componentType, GameObject fromGameObject, GameObject toGameObject) { RemoveComponentHandler(toGameObject, componentType); // 查找須要複製的 Component Component needCopyComponent = null; foreach (var component in fromGameObject.GetComponents<Component>()) { if (component.GetType() == componentType) { needCopyComponent = component; break; } } // 進行粘貼操做 // http://answers.unity3d.com/questions/907294/copy-all-components-from-a-gameobject-and-paste-to.html UnityEditorInternal.ComponentUtility.CopyComponent(needCopyComponent); UnityEditorInternal.ComponentUtility.PasteComponentAsNew(toGameObject); }
3、關聯新屬性orm
就是遍歷指定的GameObject,而後找到它附加的組件,從新設置其值便可。htm
4、替換預製對象對象
GameObject activeGameObject = Selection.activeGameObject; if (activeGameObject != null) { // 獲取當前的id if (new Regex(@"^\d+h$").IsMatch(activeGameObject.name)) { UnityEngine.Object parentObject = null; string strPrefabPath = ""; if (PrefabUtility.GetPrefabType(activeGameObject) == PrefabType.PrefabInstance) { parentObject = EditorUtility.GetPrefabParent(activeGameObject); strPrefabPath = AssetDatabase.GetAssetPath(parentObject); } // 查找id string strId = new Regex(@"h$").Replace(activeGameObject.name, ""); // 第六步 保存預製對象 string strCurrSelectPrefabName = activeGameObject.name; if (strPrefabPath.EndsWith(".prefab")) { // string[] dependPaths = AssetDatabase.GetDependencies(strPrefabPath); GameObject go = GameObject.Instantiate(GameObject.Find(strCurrSelectPrefabName)) as GameObject; PrefabUtility.ReplacePrefab(go, parentObject, ReplacePrefabOptions.ConnectToPrefab); GameObject.DestroyImmediate(activeGameObject); go.name = strCurrSelectPrefabName; AssetDatabase.Refresh(); } Debug.Log("預製對象 " + strCurrSelectPrefabName + " 修改完成。"); } else { Debug.Log("當前選中的GameObject命名不符合要求,格式:id+h。\tGameObject Name : " + activeGameObject.name); } }
最核心的幾行代碼:
一、實例化一個新的GameObject;
二、替換預製對象;
三、銷燬老的GameObject;
四、刷新資源;
對於美術的同事來說,最複雜、麻煩的莫過於從新關聯屬性,特別是骨骼動畫。由於以前沒有統一的規範,因此關聯哪一段動畫其實是須要一層一層找的,我看着他們找都以爲累,怎麼辦呢?我想到一個辦法,就是經過name查找新的組件,而後從新賦值關聯。經過Name查找某個GameObject下的子節點(前提條件是該Name惟一)
public static GameObject FindChildGameObject(GameObject parent, string childName) { if (parent.name == childName) { return parent; } if (parent.transform.childCount < 1) { return null; } GameObject obj = null; for (int i = 0; i < parent.transform.childCount; i++) { GameObject go = parent.transform.GetChild(i).gameObject; obj = FindChildGameObject(go, childName); if (obj != null) { break; } } return obj; }
上面基本上實現了,組件幾個經常使用的方法:
一、添加組件(先複製後粘貼);
二、刪除組件;
三、經過名字查找子組件;
四、更新預製對象;