Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Discussion How I never use GetComponent when pooling

Discussion in 'Scripting' started by Ali_V_Quest, Feb 14, 2023.

  1. Ali_V_Quest

    Ali_V_Quest

    Joined:
    Aug 2, 2015
    Posts:
    138
    for the full article, visit:
    https://www.alivquest.com/post/ditching-unity-s-get-component-with-the-last-enabled-pattern


    Hi,
    when getting 10s or 100s of items from a pool per frame, the GetComponent<> call can hinder performance, especially in mobile & VR.
    - to avoid that, I designed the last enabled pattern
    - it makes use of the builtin OnEnable() method to set a static lastEnabled variable to the spawned instance

    here is what it looks like:

    Code (CSharp):
    1.  public class BulletRefs: MonoBehaviour
    2.     {
    3.         public static BulletRefs lastEnabled;
    4.    
    5.         void OnEnable(){
    6.             lastEnabled=this;
    7.         }
    Code (CSharp):
    1. GameObject recycledBulletGameObject = MyBulletPool.SpawnBullet();
    2. recycledBulletGameObject.SetActive(true);
    3. BulletRefs recycledBulletRefs = BulletRefs.lastEnabled;

    I hope you find this helpful
     
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,606
    I feel like you could pretty easily never need
    GetComponent<T>
    by just typing your pool to the bullet type, and instantiating your bullets using a component reference (which returns a reference to the new component).
     
    Kurt-Dekker and Bunny83 like this.
  3. SF_FrankvHoof

    SF_FrankvHoof

    Joined:
    Apr 1, 2022
    Posts:
    780
    I'd also like to add that methods such as OnEnable() are found & called by the engine via Reflection. So not really the best way to do it.
     
  4. AngryProgrammer

    AngryProgrammer

    Joined:
    Jun 4, 2019
    Posts:
    490
    Unity provides ton's of simplification to coding. We have component game object, we can drag and drop components between components to make easy references, we can store ready half product as Prefab and its Variants. I never had need of using GetComponent at all.
     
  5. Ali_V_Quest

    Ali_V_Quest

    Joined:
    Aug 2, 2015
    Posts:
    138
    I used this design because I was using a generic game object pool.
    but a typed pool should solve the issue.
    Thanks for the tip
     
  6. Ali_V_Quest

    Ali_V_Quest

    Joined:
    Aug 2, 2015
    Posts:
    138
    Thanks for pointing that out, I'll try to benchmark it & check how slow is Unity when calling OnEnable vs GetComponent


    Update:
    Did some research & it looks like Unity caches the references to OnEnable() & other methods ( doesn't use reflection everytime )
    https://blog.unity.com/technology/1k-update-calls
    - the magic methods still have some overhead though as the Unity blog post mentions
     
    Last edited: Feb 14, 2023
    Bunny83 likes this.
  7. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,913
    Right, that's why even references to prefabs should not use a "GameObject" reference but a reference of one of the most useful components on that prefab. That way Instantiate will directly return the cloned component. I think I never used a serialized GameObject variable, ever. Even if I don't have a custom script, I would always pick the Transform component as a handle and not the GameObject. In most cases you actually need the transform anyways.
     
    Kurt-Dekker and Ali_V_Quest like this.
  8. Ali_V_Quest

    Ali_V_Quest

    Joined:
    Aug 2, 2015
    Posts:
    138

    Yeah, it's usually a good idea to reference the specific components instead of game objects
    - I used the lastEnabled pattern because the pool I use works with game objects & I would need to use GetComponent after getting something from the gameObject pool
     
  9. tleylan

    tleylan

    Joined:
    Jun 17, 2020
    Posts:
    616
    Yipes I might need to make some changes here. Can you take a moment to explain a bit more and the limits if any? If for instance I reference a PlayerPrefab in a script assigned in the inspector should I make that the transform instead? I also have a number of private prefabs that I instantiate at runtime. Should these tend to be transforms as well? Thanks.
     
  10. Ali_V_Quest

    Ali_V_Quest

    Joined:
    Aug 2, 2015
    Posts:
    138

    Unless you're using GetComponent in Update(), then you should be good