Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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
3
Question by frarees · Oct 10, 2013 at 10:33 AM · editorruntimecomponentcachefast

Fastest way to get all components on GameObject?

I'm developing a serialization tool on top of Unity. Every time I create an object and want to deserialize data to it, I have to retrieve all components to provide them with sensible data. The soonest I can do this is on Awake and via GetComponents(). However, this isn't as fast as I would like it to, when components per GO are high or there are too much GOs to deserialize.

Is there a faster way to get every component a GO have? I imagine you cannot cache them at editor (I presume the instances are generated once instantiated.. makes sense..), and I don't see any property on GameObject exposing the Component[] I need.

Note that I want to retrieve every component on my GameObject just after its instantiation (and wisely, in the same tick) – the objects won't be residing on the scene at build time, but will be instantiated at some point of the execution

Thanks

Comment
Add comment · Show 2
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 Sisso · Oct 10, 2013 at 05:08 PM 0
Share

When you said

the objects won't be residing on the scene at build time, but will be instantiated at some point of the execution

Are you talking about full dynamic objects created by script (new GameObject("name"))? And not instantiations from prefabs (GameObject.Instantiate(prefab))?

avatar image frarees · Oct 10, 2013 at 05:13 PM 0
Share

In this case it's always about prefab instantiation.

2 Replies

· Add your reply
  • Sort: 
avatar image
7
Best Answer

Answer by whydoidoit · Oct 10, 2013 at 02:53 PM

Try this:

 using UnityEngine;
 using System.Collections;
 [ExecuteInEditMode]
 public class CacheComponents : MonoBehaviour
 {
         public List<Component> components;
         public bool cacheNow;
        
 
         void Awake()
         {
              if(!Application.isPlaying)
                  Cache();
         }
 
         void Update()
         {
             if(cacheNow)
             {
                cacheNow = false;
                Cache();
             }
         }
 
         void Cache()
         {
              components = new List<Component>();
              foreach(var component in GetComponents<Component>())
              {
                   if(component != this) components.Add(component);
              }
         }
 
 }
Comment
Add comment · Show 21 · 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 whydoidoit · Oct 10, 2013 at 02:55 PM 0
Share

You also be wise to cache the GetGet$$anonymous$$ethod and GetSet$$anonymous$$ethods of the properties or create delegates to read and write field values for each individual type and cache those so you only do it once. It would be very nice if you could do that in the editor, but I can't think of a way.

avatar image whydoidoit · Oct 10, 2013 at 02:56 PM 1
Share

Note for best performance use two scripts - one to hold the list and the one to cache it. You can then destroy the caching one when the app is running to avoid it's pointless Update function from running.

Another choice is to write a custom editor for this class that calls Cache in the Editor rather than the Update mode used here (which I hacked out for brevity to demonstrate the principle).

avatar image frarees · Oct 10, 2013 at 03:41 PM 0
Share

But I'm talking of instances that I haven't even created yet on editor. They will be created once the deserialized decided they need to. For already created instances, but my problem right now is the new ones. The already existent ones can be cached the way you explain, probably. I don't get the GetGet$$anonymous$$ethod part btw.

avatar image whydoidoit · Oct 10, 2013 at 04:34 PM 0
Share

I feel a bit lost on that = are you talking about components that are added to the game object at runtime?

Normally you want to get the existing components and deserialize data into them from you storage. If there are components on the game object that aren't there in the editor before the game is played then you have no choice but to look for them at runtime. If you have components that you want to fill with values that are defined before playing then this is the right approach.

GetGet$$anonymous$$ethod is a way of getting the specific method that returns a value from a property without needing to use Invoke (which is stupidly slow). You can create a specific instance of a delegate using GetGet$$anonymous$$ethod for a property that will be as fast as calling it natively.

It was just a tip, I have no idea how you are intending to fill in these values...

avatar image whydoidoit · Oct 10, 2013 at 05:56 PM 1
Share

Yes so long as those things are components on or beneath the instantiated object - this has to work or no prefabs that self referenced would ever fly :)

Show more comments
avatar image
0

Answer by Sisso · Oct 10, 2013 at 01:13 PM

A partial and non so generic solution.

Before build you iterate between all Prefabs and objects in scene, then, attach a script that cache all information that you will need. For version 2, if you don't want to dirt your objects you should catalog in a unique prefab, but you have a problem to identify wich object it is or for wich prefab (you can add a script with the id... ops, failed again :P).

If you need to interate between prefabas and scenes you can use this. It is a incrible usefull stuff to make dirt scripts and prepare your build.

https://github.com/sisso/ngui-hdsd/blob/master/Assets/Scripts/Editor/EditorUtils.cs


Edited: Try to explain with code

Lets try, I will explain in code (not compiled :P)

This is your utility class that cache the components names

 class ComponentsCache extends MonoBehaviour {
     static function GenareteCache(obj: GameObject) {
           var gc = obj.GetComponent(ComponentsCache);
           if (!gc) gc = obj.AddComponent(ComponentsCache);
 
           var names: String[] = [c.name for (c in obj.GetComponents())];
           gc.componentNames = names;
     }
 
     static function GetComponentNames(obj: GameObject) {
          // if we have build time cached
          var gc = obj.GetComponent(ComponentsCache);
          if (gc) return gc.componentsNames;
          
          // if we don't have a cache, like in the editor or in objects created in runtime not derived from prefabs, we use the old fashion
          return [c.name for (c in obj.GetComponents())];
     }
     
     var componentsNames: String[];
 }

This is the code that you run on build time to cache all objects. Generally, for release only.

 var ForAll = function() {
     // for all objects generate cache
     for (var obj in GameObject.FindObjectOfType(GameObject)) {
         ComponentsCache.GenerateCache(obj);
     }
 }
 
 EditorUtils.ForEachScene(function (sceneName: String) {
     // we are in a scene, execute for all
     ForAll();
     return true;
 });
 
 EditorUtils.ForEachPrefab(function (obj: GameObject) {
     // we are in a scene with prefab obj instantiated, execute for all
     ForAll();
     return true;
 });

Now when you need at runtime the components names of any object you simple do

 components = ComponentsCache.GetComponentNames(anyRuntimeObject)





Comment
Add comment · Show 3 · 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 frarees · Oct 10, 2013 at 01:40 PM 0
Share

So you mean just accessing a component (created at build time) that contains all the information previously gathered at build time? I don't understand your solution very well, but sounds interesting. Could you explain? I need to access each instance's components, so I presume I need to access them after instantiation.

avatar image Sisso · Oct 10, 2013 at 02:15 PM 0
Share

Take I a look if I am going in the wrong direction :P

avatar image Sisso · Oct 10, 2013 at 05:29 PM 0
Share

Ok.... $$anonymous$$y answer sucks. I solve the problem to get information from components without need to access it, but what you want is to update.

Have you try dig into Reflection?

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

18 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

Related Questions

Get if any component in gameObject has changed 1 Answer

Way to scale all assets in a scene 1 Answer

[RESOLVED]How to get all available parameters from target Component 3 Answers

Script component in Editor vs. runtime-dependent inheritance 0 Answers

MetaData class can't be loaded and failed to load window layout 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