Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Question UnityEngine.Pool -> ObjectPool doesn't do pooling

Discussion in 'Scripting' started by kfir124, Nov 1, 2022.

  1. kfir124

    kfir124

    Joined:
    Oct 22, 2022
    Posts:
    3
    I know it sounds weird but it feels like using the new ObjectPool doesn't do what it is supposed to do.
    I have the following code:
    Code (CSharp):
    1.     void Start() {
    2.         PopulatePool();
    3.     }
    4.  
    5.     void PopulatePool() {
    6.         Debug.Log("Populate!");
    7.         pool = new ObjectPool<GameObject>(
    8.         () => {
    9.             Debug.Log("Create");
    10.             GameObject enemy = Instantiate(enemyPrefab);
    11.             enemy.GetComponent<EnemyHealth>().SetPool(pool);
    12.             enemy.GetComponent<EnemyMover>().SetPool(pool);
    13.             return enemy;
    14.         },
    15.         (enemy) => {
    16.             Debug.Log("Get");
    17.             enemy.SetActive(true);
    18.         },
    19.         (enemy) => {
    20.             enemy.SetActive(false);
    21.             Debug.Log("Release");
    22.         },
    23.         (enemy) => Destroy(enemy),
    24.         true, 10, 10);
    25.     }
    When I run the game the pool does nothing, it doesn't initiate the 10 objects at the start but I see in the console
    "Populate!"

    Ok so maybe somewhy (although it defeats the purpose of pooling) it only instantiate when using pool.Get() so I tried to do that
    Code (CSharp):
    1.     void Start() {
    2.         PopulatePool();
    3.         EnemySpawner();
    4.     }
    5.  
    6.     void PopulatePool() {
    7.         Debug.Log("Populate!");
    8.         pool = new ObjectPool<GameObject>(
    9.         () => {
    10.             Debug.Log("Create");
    11.             GameObject enemy = Instantiate(enemyPrefab);
    12.             enemy.GetComponent<EnemyHealth>().SetPool(pool);
    13.             enemy.GetComponent<EnemyMover>().SetPool(pool);
    14.             return enemy;
    15.         },
    16.         (enemy) => {
    17.             Debug.Log("Get");
    18.             enemy.SetActive(true);
    19.         },
    20.         (enemy) => {
    21.             enemy.SetActive(false);
    22.             Debug.Log("Release");
    23.         },
    24.         (enemy) => Destroy(enemy),
    25.         true, 10, 10);
    26.     }
    27.  
    28.     void EnemySpawner() {
    29.         IEnumerator main() {
    30.             while (this.isActiveAndEnabled) {
    31.                 Debug.Log($"{pool.CountAll}");
    32.                 pool.Get();
    33.                 yield return new WaitForSeconds(spawnDelay);
    34.             }
    35.         }
    36.  
    37.         StartCoroutine(main());
    38.     }
    39.  
    Now each time I do a pool.Get(); it instantiate a new instance, but if I let it run for a while it never stops instantiating instances, the pool just keeps growing forever 1000,2000,3000 objects basically not acting like a pool at all.

    I expected the pool to not increase above the max limit I gave it, this is what I see in the log (will copy from the middle cause it is never ending)

    ...
    Create
    Get
    20
    Create
    Get
    21
    Create
    Get
    22
    ...


    I disabled the releasing on purpose(enemy prefab doesn't do any destroy or release now) to first check why the pool doesn't behave like a pool, when I tried to release stuff it didn't help much it seems like released items are going back to the pool fine but still if I create quicker than I release then the pool just keeps expanding and issuing a create command each time I use Get instead of creating it all at the startup. (and also the scene has tons of objects because nothing ever gets destroyed even though I added in the pool the destroy callback)

    I probably miss something here but not sure what
    My pool variable looks like this if it matters:
    ObjectPool<GameObject> pool;
     
    Last edited: Nov 1, 2022
  2. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,051
    Unity's pooling classes do not create objects by themselves, they will only fill up as you release objects and later return them again to be re-used. If you want to pre-warm the pool, you have to get and immediately release a given number of objects.

    The argument you set in its constructor is
    defaultCapacity
    . It only sets the initial capacity of the list it creates to hold the objects, to avoid reallocating the backing array a couple of times when objects are added to the list. It does not mean that it creates that many objects.
     
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,947
  4. kfir124

    kfir124

    Joined:
    Oct 22, 2022
    Posts:
    3
  5. kfir124

    kfir124

    Joined:
    Oct 22, 2022
    Posts:
    3
    Hmm I see it explains some stuff, but why it does not honor the "maxSize" as well? objects are created infinitely I reached more than 1000 objects in the scene(in the pool) even though I set the maxSize to 10.

    EDIT: ok I see once I stop spamming the pool with Get(), it actually started to destroy the excess (it stays at a number higher than defaultCount but close to it, and lower than maxSize), also all the counting of the pool like CountActive / CountAll seems really inaccurate I had to manually count the objects in the scene(that belongs to the pool).
     
    Last edited: Nov 1, 2022
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,947
    The case where it might make a difference. Remember: it has an extremely high cost. Don't do it unless you must.

    DO NOT OPTIMIZE "JUST BECAUSE..." If you don't have a problem, DO NOT OPTIMIZE!

    If you DO have a problem, there is only ONE way to find out. Always start by using the profiler:

    Window -> Analysis -> Profiler

    Failure to use the profiler first means you're just guessing, making a mess of your code for no good reason.

    Not only that but performance on platform A will likely be completely different than platform B. Test on the platform(s) that you care about, and test to the extent that it is worth your effort, and no more.

    https://forum.unity.com/threads/is-...ng-square-roots-in-2021.1111063/#post-7148770

    Remember that optimized code is ALWAYS harder to work with and more brittle, making subsequent feature development difficult or impossible, or incurring massive technical debt on future development.

    Notes on optimizing UnityEngine.UI setups:

    https://forum.unity.com/threads/how...form-data-into-an-array.1134520/#post-7289413

    At a minimum you want to clearly understand what performance issues you are having:

    - running too slowly?
    - loading too slowly?
    - using too much runtime memory?
    - final bundle too large?
    - too much network traffic?
    - something else?

    If you are unable to engage the profiler, then your next solution is gross guessing changes, such as "reimport all textures as 32x32 tiny textures" or "replace some complex 3D objects with cubes/capsules" to try and figure out what is bogging you down.

    Each experiment you do may give you intel about what is causing the performance issue that you identified. More importantly let you eliminate candidates for optimization. For instance if you swap out your biggest textures with 32x32 stamps and you STILL have a problem, you may be able to eliminate textures as an issue and move onto something else.

    This sort of speculative optimization assumes you're properly using source control so it takes one click to revert to the way your project was before if there is no improvement, while carefully making notes about what you have tried and more importantly what results it has had.
     
    kfir124 likes this.
  7. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    4,191
    Get the free MasterObjectPooler from the store and stop worrying about the pool. ;)