• 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
0

Answer by Gwom · Aug 31, 2016 at 02:02 PM

Just changing to look for a copy of the component int he target object, else Unity will crash trying to add the same component twice - if it is found, it writes over the component.

     public static Component CopyComponent(Component original, GameObject destination)
     {
         Component[] m_List = destination.GetComponents<Component>();
         System.Type type = original.GetType();
         System.Reflection.FieldInfo[] fields = type.GetFields();
 
         foreach (Component comp in m_List)
         {
             // If we already have one of them
             if (original.GetType() == comp.GetType())
             {
                 foreach (System.Reflection.FieldInfo field in fields)
                 {
                     field.SetValue(comp, field.GetValue(original));
                 }
                 return comp;
             }
         }
 
         // By here, we need to add it
         Component copy = destination.AddComponent(type);
 
         // Copied fields can be restricted with BindingFlags
         foreach (System.Reflection.FieldInfo field in fields)
         {
             field.SetValue(copy, field.GetValue(original));
         }
 
         return copy;
     }
Comment
Add comment · 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
0

Answer by GingerLoaf · Sep 01, 2016 at 01:29 AM

I was recently tasked with a similar problem here and I must say that I do agree that it probably isn't great practice to create things dynamically that are so important. It gets really hard to debug the problem when everything has been dynamically created. Imagine a confused developer on your team spending hours trying to find a prefab that was spawned in when it really doesn't exist in the first place?

I solved this problem by thinking about it differently. Instead of copying components during run-time, I decided to think about syncing my prefabs that will be spawned in at editor time so that they have essentially identical components. Using this mindset, I was able to create a "template" prefab that houses all my components that I want and then I created a unity "AssetModificationProcessor" that sniffed for my template to be modified and saved. Once it is saved, I scrape up all the prefabs that I want to sync to it and just add all my components and use "UnityEditor.EditorUtility.CopySerialized" to copy data from the template component to the new or existing component.

This basically means that every time another developer on my team modifies the template, all the components on the template will then be copied over to my player prefabs while in-editor.

This allows me to define the set of components one time and mirror that into multiple prefabs at editor time so that my objects all spawn with identical components at runtime :).

Here is an adaptation of my script for reference (note that the paths don't map to real things. You would have to change the prefab/asset paths in your environment to see this work):

 using System.Collections.Generic;
 using UnityEditor;
 using UnityEditor.VersionControl;
 using UnityEngine;
 
 public class FileModificationWarning : UnityEditor.AssetModificationProcessor
 {
     static string[] OnWillSaveAssets(string[] paths)
     {
         List<string> pathsToSave = new List<string>();
         pathsToSave.AddRange(paths);
 
         for (int i = 0; i < paths.Length; i++)
         {
             // ZAS: we only care about our special prefab. Not anything else
             if (paths[i].Contains("Prefabs/VisualEffects"))
             {
                 var visualEffectsPrefab = AssetDatabase.LoadAssetAtPath<GameObject>(paths[i]);
                 if (visualEffectsPrefab != null)
                 {
                     SynchronizeVisualEffectsToPlayerPrefabs(visualEffectsPrefab as GameObject, pathsToSave);
                 }
                 else
                 {
                     Debug.LogErrorFormat("Failed to load visual effects prefab at path {0}", paths[i]);
                 }
             }
         }
 
         return pathsToSave.ToArray();
     }
 
     private static void SynchronizeVisualEffectsToPlayerPrefabs(GameObject visualEffectsPrefab, List<string> pathsToSave)
     {
         List<string> errors = new List<string>();
         if (SychronizePlayerEyeWithVisualEffectPrefab("PlayerA", visualEffectsPrefab, errors)) { pathsToSave.Add("PlayerA"); }
         if (SychronizePlayerEyeWithVisualEffectPrefab("PlayerB", visualEffectsPrefab, errors)) { pathsToSave.Add("PlayerB"); }
         if (SychronizePlayerEyeWithVisualEffectPrefab("PlayerC", visualEffectsPrefab, errors)) { pathsToSave.Add("PlayerC"); }
         if (SychronizePlayerEyeWithVisualEffectPrefab("PlayerD", visualEffectsPrefab, errors)) { pathsToSave.Add("PlayerD"); }
 
         if (errors.Count > 0)
         {
             for (int i = 0; i < errors.Count; i++)
             {
                 EditorUtility.DisplayDialog("Sync Error", errors[i], "Ok");
             }
         }
 
         EditorUtility.DisplayDialog("Sync visual changes to prefabs", "All player prefabs were modified because a change to the visual asset prefab was detected. Remember to check in the player prefabs!", "Ok!");
     }
 
     private static bool SychronizePlayerEyeWithVisualEffectPrefab(string playerPrefabPath, GameObject visualEffectsPrefab, List<string> errors)
     {
         var potentialPlayerPrefab = Resources.Load(playerPrefabPath) as GameObject;
         if (potentialPlayerPrefab == null)
         {
             errors.Add(string.Format("{0}: Failed to load prefab", playerPrefabPath));
             return false;
         }
 
         // ZAS: if you use version control then we need to check out the file we are changing first
         if (Provider.hasCheckoutSupport)
         {
             Provider.Checkout(potentialPlayerPrefab, CheckoutMode.Asset);
         }
 
         // ZAS: get all components so we can iterate through and copy each one
         var components = visualEffectsPrefab.GetComponentsInChildren<Component>(true);
         for (int i = 0; i < components.Length; i++)
         {
             // ZAS: everything has a transform on it. If you want to sync this then just remove this statement and let it pull the serialized data :)
             if (components[i] is Transform)
             {
                 continue;
             }
 
             // ZAS: lets find the component first and just use that if we find it
             var foundComponents = potentialPlayerPrefab.GetComponentsInChildren(components[i].GetType(), true);
             Component existingComponent = null;
             if(foundComponents.Length > 0)
             {
                 existingComponent = foundComponents[0];
             }
 
             // ZAS: remove other instances to make sure there is only one!
             if(foundComponents.Length > 1)
             {
                 for (int j = 1; j < foundComponents.Length; j++)
                 {
                     Component.DestroyImmediate(foundComponents[j], true);
                 }
             }
 
             // ZAS: did not find a component... time to add a new one!
             if (existingComponent == null)
             {
                 existingComponent = potentialPlayerPrefab.AddComponent(components[i].GetType());
             }
             
             // ZAS: copy the serialied data over from our template to our new or existing component (this is where all serialized fields are synchronized)
             EditorUtility.CopySerialized(components[i], existingComponent);
         }
 
         // ZAS: we want to make sure that our changes cause the assets to be marked for saving
         EditorUtility.SetDirty(potentialPlayerPrefab);
         return true;
     }
 }

Just thought I would drop by and share :)

Comment
Add comment · 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
-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? ^__^"

avatar image
-1

Answer by theuncas · Apr 19, 2018 at 07:40 PM

check it out : https://materiagame.blogspot.fr/2018/04/unity-tricks-01-duplicate-component-on.html

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

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

How to add a component to all selected objects? 1 Answer

Import assets, linking their components automaticly. 0 Answers

Retrieving Script component from gameobject. 0 Answers

Model - get mesh component 0 Answers

Character controller not fitting through door 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