1. 程式人生 > >Unity插件擴展中組件常用的幾個方法

Unity插件擴展中組件常用的幾個方法

重新 paths form log public 名字查找 實例化 dna mat

最近為美術編寫一個Unity編輯器的擴展,主要為了減輕美術在修改預制對象時的機械化操作的繁瑣和出錯。具體實現的幾個功能:

1、刪除指定組件;

2、復制、粘貼指定的組件;

3、重新關聯新的屬性;

4、重新保存預制對象;

一、刪除指定類型的組件

public static void RemoveComponentHandler(GameObject gameObject, Type componentType)
    {
        foreach (var component in gameObject.GetComponents<Component>())
        {
            
if (component.GetType() == componentType) { GameObject.DestroyImmediate(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); }

三、關聯新屬性

就是遍歷指定的GameObject,然後找到它附加的組件,重新設置其值即可。

四、替換預制對象

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);
    }           
}

最核心的幾行代碼:

1、實例化一個新的GameObject;

2、替換預制對象;

3、銷毀老的GameObject;

4、刷新資源;

對於美術的同事來講,最復雜、麻煩的莫過於重新關聯屬性,特別是骨骼動畫。因為之前沒有統一的規範,所以關聯哪一段動畫實際上是需要一層一層找的,我看著他們找都覺得累,怎麽辦呢?我想到一個辦法,就是通過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;
    }

上面基本上實現了,組件幾個常用的方法:

1、添加組件(先復制後粘貼);

2、刪除組件;

3、通過名字查找子組件;

4、更新預制對象;

Unity插件擴展中組件常用的幾個方法