Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • 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
15
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, which 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
Add comment · 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.

9 Replies

· Add your reply
  • Sort: 
avatar image
25

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

Sometimes a prefab is not suitable.

This 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
Add comment · Show 8 · 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
11

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 this 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
Add comment · 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 shared$$anonymous$$aterial is sufficient. So for that one can replace line 15 to :

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

and we can just set manually after calling your function:

 sourceComp.material = targetComp.shared$$anonymous$$aterial;
 sourceComp.materials = targetComp.shared$$anonymous$$aterials;
  

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 $$anonymous$$Volume is not supported anymore. Use $$anonymous$$-, maxDistance and rolloff$$anonymous$$ode ins$$anonymous$$d. Which I reconciled via this link. So just add

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


avatar image
3

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 child 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: this doesn't work with all components because some have internal variables which you can't access from outside.

Comment
Add comment · 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
2

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
Add comment · 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 henrimh · Nov 13, 2017 at 01:34 PM 0
Share

Saved my day that EditorUtility.CopySerialized

Didn't come across that in Unity $$anonymous$$anual or Google searches.

avatar image
-1

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

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

Comment
Add comment · 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.

Follow this Question

Answers Answers and Comments

32 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

Related Questions

Multiple Game Objects, different components 1 Answer

Flash raw animation data to Unity 0 Answers

Cant destroy object, dont know how to fix help pls 1 Answer

Unity editor bugging out 4 Answers

UNet bugs all over the place, fixed after re-building the Player prefab. 0 Answers


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