• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
Question by Asvaronn · May 17, 2013 at 09:59 AM · componentsruntime-generation

Copy a component at runtime

I need to copy a component with all its values at runtime (would save me a lot of time), but I don't know how to do that. Google only brings results where people want to copy a component in editormode, w$$anonymous$$ch is available in Unity4 anyway.

My use-case: I have several objects and I want to make them burnable. For that, I would like to copy the particle components (legacy) of my fire-prefab and add them to every object I mark as "burnable" in a script, so I can switch on the particleemitter by code if it should start burning. I could do it by hand in editor, but that's rather time-consuming. So, is there a way to do that easily by code?

Comment
Tomer-Barkan
scanzy
maccesch
NeatWolf
ahungrybear
Priato
jessmlilly
jack1993224
stevospinks
smit17av
MaxIzrinCubeUX
abolfazlhosnian
Mehrdad995
SamFernGamer4k
glenneroo
And 1 more...

People who like this

16 Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Fattie · May 17, 2013 at 11:49 AM 0
Share

FWIW, there are a couple tings in the asset store along the lines of "copy cool s*** at run time!" Get them and see if they're any good for you.

8 Replies

· Add your reply
  • Sort: 
avatar image

Answer by Shaffe · Dec 04, 2013 at 12:22 PM

Sometimes a prefab is not suitable.

T$$anonymous$$s method allows to copy fields values on a new component using the reflection API.

 Component CopyComponent(Component original, GameObject destination)
 {
     System.Type type = original.GetType();
     Component copy = destination.AddComponent(type);
     // Copied fields can be restricted with BindingFlags
     System.Reflection.FieldInfo[] fields = type.GetFields(); 
     foreach (System.Reflection.FieldInfo field in fields)
     {
        field.SetValue(copy, field.GetValue(original));
     }
     return copy;
 }

And here the version with generic typing:

 T CopyComponent<T>(T original, GameObject destination) where T : Component
 {
     System.Type type = original.GetType();
     Component copy = destination.AddComponent(type);
     System.Reflection.FieldInfo[] fields = type.GetFields();
     foreach (System.Reflection.FieldInfo field in fields)
     {
         field.SetValue(copy, field.GetValue(original));
     }
     return copy as T;
 }


Comment
komodor
Benjiko99
Alex 3D
zombience
Fattie
Marc-Uberstein
kk99
hangemhigh
AngelGabriel
ahungrybear
Rapcyss
Priato
henrimh
JPhilipp
Mr_Mow
And 15 more...

People who like this

26 Show 9 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image DAVco · Aug 21, 2014 at 03:58 PM 0
Share

I was able to use your generic version quite successfully, with the addition of the BindingFlags bitmask to the getFields function ( GetFields(BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic) )

However, this only seems to work for components created in the project - not for build in components such as BoxCollider. Any ideas on how we can improve the method to also handle these components?

avatar image ShawnFeatherly · Mar 18, 2015 at 12:23 AM 1
Share

The answer here handles built-in components: http://answers.unity3d.com/questions/530178/how-to-get-a-component-from-an-object-and-add-it-t.html

avatar image rolfewiz · Sep 17, 2015 at 05:32 PM 1
Share

@DAVco I think you need to add BindingFlags.FlattenHierarchy to get fields from inherited types.

avatar image zombience · Dec 29, 2015 at 03:32 AM 0
Share

thanks for this! had an odd case where prefabs weren't appropriate and needed to verify that an artist had correct components configured properly.

Thanks!

avatar image krisventure · Oct 20, 2016 at 03:01 PM 0
Share

This didn't work for ParticleSystemRenderer component (so I guess for any ParticleSystem**** components). I know it's a bit different in nature but Unity 5 has made many particle system properties independent 'components' which were earlier accessible from ParticleSystem component, now you need to call eg. GetComponent< ParticleSystemRenderer >(). property. Interesting however, that the version of @vladipus works for these components too (throws an error message but seem to finish copying all properties).

Show more comments
avatar image

Answer by turbanov · Dec 28, 2015 at 02:46 PM

I've edited the Shaffe's version to utilize properties and check for static variables, component reuse instead of creating new. I'm currently using t$$anonymous$$s technique in the editor, however.

     T CopyComponent<T>(T original, GameObject destination) where T : Component
     {
         System.Type type = original.GetType();
         var dst = destination.GetComponent(type) as T;
         if (!dst) dst = destination.AddComponent(type) as T;
         var fields = type.GetFields();
         foreach (var field in fields)
         {
             if (field.IsStatic) continue;
             field.SetValue(dst, field.GetValue(original));
         }
         var props = type.GetProperties();
         foreach (var prop in props)
         {
             if (!prop.CanWrite || !prop.CanWrite || prop.Name == "name") continue;
             prop.SetValue(dst, prop.GetValue(original, null), null);
         }
         return dst as T;
     }

Comment
Fattie
krisventure
Metu
ahungrybear
ilmario
GameDevBryant
maxizrin
e-ivkov
sepnax
abolfazlhosnian
Mehrdad995
grofie
LushkinR
cdiggins

People who like this

12 Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image krisventure · Oct 20, 2016 at 03:37 PM 2
Share
  • Only this solution worked for ParticleSystemRenderer component in Unity 5!

In editor mode it gives a warning when it copies any material property that this can result in memory leaks and copying sharedMaterial is sufficient. So for that one can replace line 15 to :

 if (!prop.CanWrite || !prop.CanWrite || prop.Name == "name" || prop.PropertyType.Equals(typeof(Material)) || prop.PropertyType.Equals(typeof(Material[]))) continue;

and we can just set manually after calling your function:

 sourceComp.material = targetComp.sharedMaterial;
 sourceComp.materials = targetComp.sharedMaterials;
  

or just place the replacement code inside your loop.

avatar image CoughE · Feb 28, 2019 at 09:27 PM 0
Share

For copying an audiosource in unity 2018.3, I got the error minVolume is not supported anymore. Use min-, maxDistance and rolloffMode instead. Which I reconciled via this link. So just add

  if(!propertyInfo.IsDefined(typeof(ObsoleteAttribute), true))
      propertyValue = propertyInfo.GetValue(myComponent,null); 


avatar image

Answer by Bunny83 · May 17, 2013 at 11:30 AM

You should create a prefab of your particle effect and simply Instantiate it at runtime and attach it as c$$anonymous$$ld object.

Components are always bound to the GameObject they're attached to. The only way is to create the same component on your target GameObject and copy all variables manually. Note: t$$anonymous$$s doesn't work with all components because some have internal variables w$$anonymous$$ch you can't access from outside.

Comment
Fattie
save
ahungrybear

People who like this

3 Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Asvaronn · May 17, 2013 at 01:02 PM 0
Share

I would of course do that if I would not like to have it as a mesh particle emitter... which requires me to add the components to the object that should emit the particles. And it is not only this case. It's not the first time that I wish I could copy a component with all it's values, it would just be very useful ;)

avatar image

Answer by wa1bo · Nov 22, 2014 at 02:36 PM

For editor only scripts, you can use: EditorUtility.CopySerialized

For runtime, you can use SerializedObject.CopyFromSerializedProperty (iterate on the properties, and applying each one)

Comment
henrimh
ivaylo5ev
grofie
Tomer-Barkan

People who like this

2 Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image henrimh · Nov 13, 2017 at 01:34 PM 0
Share

Saved my day that EditorUtility.CopySerialized

Didn't come across that in Unity Manual or Google searches.

avatar image mtschoen · Sep 29, 2022 at 04:43 AM 0
Share

Unfortunately, SerializedObject is not available at runtime.

avatar image

Answer by SuperSboy · Apr 18, 2017 at 09:15 AM

UnityEditorInternal.ComponentUtility.CopyComponent(original); UnityEditorInternal.ComponentUtility.PasteComponentAsNew(destinationObject);

Comment
phobos2077
NeatWolf
Tomer-Barkan

People who like this

-1 Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image NeatWolf · Aug 26, 2020 at 10:31 AM 2
Share

Yes but, I don't think it works at runtime? ^__^"

  • 1
  • 2
  • ›

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

34 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Couldn't attach any components to 3D model Prefab 1 Answer

Animation curves of sub-objects not accessible 1 Answer

Associate a data object to Monobehaviours with generic 0 Answers

Component architecture problem 0 Answers

can't access a component (don't exist). 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges