- Home /
Best practice for copying Components from one GameObject to another?
Hello fellow Unity users. Im writing an Editor Script that should copy all Components from one GameObject to another. Unfortunately I have encountered some problems in doing so.
My first atempt was using the EditorUtility.CopySerialized function:
Foo from = gameObjectFrom.GetComponent<Foo>();
Foo to = gameObjectTo.AddComponentn<Foo>();
EditorUtility.CopySerialized(from, to);
CopySerialized seems to be working. Unfortunatelly later I get the Error 'Component (Foo) has a broken GameObject reference. Fixing!'
Then I tried using Reflection:
foreach(FieldInfo field in fromComponent.GetType().GetFields())
field.SetValue(toComponent, field.GetValue(fromComponent));
When I try using this on an Animation Component, it has no fields. Instead the Animation Component has 31 Properties and Im not sure if it's a good idea to reflection-set all of these properties.
So, is there a good and reliable way to copy Components from one GameObject to another and that will work with all components?
Answer by Eran-Yaacobi · Nov 10, 2013 at 09:59 PM
EditorUtility.CopySerialized should work, but if it doesn't, you can simply use the (undocumented) UnityEditorInternal.ComponentUtility class:
UnityEditorInternal.ComponentUtility.CopyComponent(copiedComponent);
UnityEditorInternal.ComponentUtility.PasteComponentAsNew(targetGameObject);
This seems to be identical to the actual commands in the component's context-menu in the inspector, so there shouldn't be any problems with it.
This comment is for people who is wishing to build a game with this code. (I didn't understand that this question was based on editor only).
I have to type "Using UnityEditorInternal" in beginning of script. And unity can't build game giving error about unityeditorinternal not being available.
This is editor code, and as such, you need to surround it with:
#if UNITY_EDITOR
// Editor code here.
#endif
This causes the compiler to ignore the content in between when building the game.
$$anonymous$$oreover, as you've mentioned, you do need to add a 'using' statement, though it should be "using UnityEditor" - there is no need to specify "UnityEditorInternal" directly. Again, UnityEditor is not available when building a game, so you need to surround the 'using' clause with the '#if UNITY_EDITOR' clause as well.
However, all this is irrelevant if the code is in an editor script (scripts under an "Editor" folder), as editor scripts are not used when building the game, and as they should contain "using UnityEditor" anyhow.
Answer by Bunny83 · May 15, 2012 at 10:14 AM
Unity uses it's own serializer. Public supported fields as well as private fields (marked with SerializeField) are serialized and saved. You could try to roll your own mechanism to find all the variables that should be serialized, or just use EditorUtility.CopySerialized which is made for this purpose ;)
If I use CopySerialized on an Animation Component I later get the 'broken GameObject reference' error as I mentioned earlier.
Answer by Nition · Sep 07, 2015 at 10:18 PM
I know this was asked years ago but I'm a bit surprised that no-ones ever actually given the most likely answer.
This may have changed now in Unity 5, but it Unity 4, when using logarithmic rolloff mode, the .maxDistance setting of an AudioSource doesn't actually determine when the sound volume reaches zero - it actually sets the point where it stops attenuating.
So unlike a linear rolloff, the smaller your maxDistance value is set, the louder your sound will be when far away.
You can fix this by adjusting the curve yourself to go to zero at or just before the maxDistance point. Unfortuntately there's currently no way to set a custom curve in script.
@Nition this looks to have been posted to the wrong question.