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

最近为美术编写一个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、更新预制对象;

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏ytkah

css自动换行如何设置?url太长会撑开页面

  我们更新文章时如果有引用其他文章一般会带一个原文url,但这个链接如果太长的话会把内容的版块撑开,整个排版乱了。那我们能不能设置css自动换行呢?如下图所示...

32750
来自专栏Python小屋

Python查找Word文件中红色和加粗的文字

背景知识:docx文件的结构分为三层,1、Docment对象表示整个文档;2、Docment包含了Paragraph对象的列表,每个Paragraph对象用来表...

44780
来自专栏前端儿

开灯问题

有n盏灯,编号为1~n,第1个人把所有灯打开,第2个人按下所有编号为2 的倍数的开关(这些灯将被关掉),第3 个人按下所有编号为3的倍数的开关(其中关掉的灯将被...

13010
来自专栏GIS讲堂

jquery判断一个div的边界是否超出另外一个div的边界

摘要:本文简单介绍jquery判断一个div的边界是否超出另外一个div的边界,如果超出边界做出相应的处理。

12340
来自专栏点滴积累

geotrellis使用(九)使用geotrellis进行栅格渲染

目录 前言 图像渲染 总结 参考链接 一、前言        前面几篇文章讲解了如何使用Geotrellis进行数据处理、瓦片生成等,今天主要表一下如何使用Ge...

38850
来自专栏木头编程 - moTzxx

PHP 自定义图片的生成与保存实例讲解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011415782/article/de...

38830
来自专栏偏前端工程师的驿站

CSS魔法堂:你真的理解z-index吗?

一、前言                                 假如只是开发简单的弹窗效果,懂得通过z-index来调整元素间的层叠关系就够了。但要将...

21850
来自专栏DeveWork

WordPress 3.9+的 TinyMCE 4 编辑器增强开发

从WordPress 3.9版本后,WordPress 默认的编辑器 TinyMCE 随之升级到了版本4,带来的问题以前在默认编辑器上的增强开发的效果可能失效。...

25660
来自专栏阿炬.NET

FineUIMvc表格数据库分页,使用CYQ.Data组件

43680
来自专栏落影的专栏

Metal入门教程(五)视频渲染

Metal入门教程(一)图片绘制 Metal入门教程(二)三维变换 Metal入门教程(三)摄像头采集渲染 Metal入门教程(四)灰度计算

90560

扫码关注云+社区

领取腾讯云代金券