Unity插件扩展中组件经常使用的几个方法

最近为美术编写一个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;
    }

 

上面基本上实现了,组件几个经常使用的方法:

一、添加组件(先复制后粘贴);

二、删除组件;

三、经过名字查找子组件;

四、更新预制对象;

相关文章
相关标签/搜索