Unity Tips 01 – Duplicate component on the fly

One day or another, you will be in front of duplicating an Unity 3D gameobject component on the fly. You think that it’s easy to do and you think that Unity provides you a simple way for doing that like a this:

gameobject.Add(otherGameObject.GetComponent());

Unfortunately, it doesn’t work. The trick is to create an extension for the GameObject class. Here is the implementation :

using UnityEngine;
using System;
using System.Reflection;
using System.Linq;

/*
*   Gameobject Class Extension
*/
namespace Utilities.Extension
{
    public static class GameObjectExtension
    {
        /// 
        /// Check it the gameobject has the specified component
        /// 
        public static bool HasComponent(this GameObject go) where T : Component
        {
            return go.GetComponentsInChildren().FirstOrDefault() != null;
        }

        /// 
        /// Return a copy of the component
        /// 
        public static T GetCopyOf(this Component comp, T other) where T : Component
        {
            Type type = comp.GetType();

            if (type != other.GetType()) return null; // type mis-match
            BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Default | BindingFlags.DeclaredOnly;
            PropertyInfo[] pinfos = type.GetProperties(flags);
            foreach (var pinfo in pinfos)
            {
                if (pinfo.CanWrite)
                {
                    try
                    {
                        pinfo.SetValue(comp, pinfo.GetValue(other, null), null);
                    }
                    catch { } // In case of NotImplementedException being thrown. For some reason specifying that exception didn't seem to catch it, so I didn't catch anything specific.
                }
            }
            FieldInfo[] finfos = type.GetFields(flags);
            foreach (var finfo in finfos)
            {
                finfo.SetValue(comp, finfo.GetValue(other));
            }
            return comp as T;
        }

        /// 
        /// Copy the component
        /// 
        public static T AddComponent(this GameObject go, T toAdd) where T : Component
        {
            return go.AddComponent().GetCopyOf(toAdd) as T;
        }
    }
}

For more information about class extensions :
https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods

Posted in Unity Tips and tagged .

2 Comments

  1. Many thanks for sharing. I'm needing to copy a collider from a prefab to a parent object and was pleased to find this. However, you haven't described how to integrate this with a project, in terms of what script to create nor how to call it. Can you add an example of calling the extension to add a copied component?Cheers!

Leave a Reply

Your email address will not be published. Required fields are marked *