Using reflection it is impossible to completely copy a component.

Hello,

I’ve been looking into copying components in runtime and would like to debunk the mention that this can be done with reflection. There have been many posts claiming that this can in fact be done with reflection but the solutions fail to consider that components such as Rigidbodys and LineRenderers are not pure components and have important properties stored in the classes above them. ie “linerenderer” inherits from “renderer” that holds properties for material that cannot be copied using reflection.

The below code represents a copy function that works well on most component but will fail at the above mentioned components.

    public static T AddCopy<T>(this GameObject me, T original) where T : Component
    {
        if (original == null)
            throw new Exception("dont give me null");

        Type type = original.GetType();
        Component copy = me.AddComponent<T>();

        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(copy, pInfo.GetValue(original, null), null);
                }
                catch { }
              
            }
        }

        FieldInfo[] fInfos = type.GetFields(flags);
        foreach (var fInfo in fInfos)
        {
            fInfo.SetValue(copy, fInfo.GetValue(original));
        }
        return copy as T;
    }

This is well understood: Unity presents you a scripting API to give you limited control of the C++ (native code engine) side objects that it uses to run the game.

This is simply the limit of the API: if Unity let you further into their game engine to modify anthing you like, they would have to drastically extend the limits of their API boundary surface, making the entire engine far harder for them to maintain.

1 Like

I haven’t tried this myself, so I’m not saying you’re wrong … However, did you try using BindingFlags.FlattenHierarchy? That might provide a few more of the properties from the classes “above”.

You can also walk the inheritance chain using reflection, so it might be possible/necessary to walk up the chain in order to copy those properties.