Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice
  2. Ever participated in one our Game Jams? Want pointers on your project? Our Evangelists will be available on Friday to give feedback. Come share your games with us!
    Dismiss Notice

PoolManager [By Path-o-logical-Games]

Discussion in 'Assets and Asset Store' started by Rafes, Sep 13, 2011.

  1. Rafes

    Rafes

    Joined:
    Jun 2, 2011
    Posts:
    764
    Unity can't do this so PoolManager can't either. You must use prefabs.

    You could experiment with instantiating (spawning) instances of instances. Meaning you could try adding an instance to the scene manually and then trying to pool a child object. It could work....accidentally...though it is not designed to do so.
     
  2. Ghopper21

    Ghopper21

    Joined:
    Aug 24, 2012
    Posts:
    170
    Thanks @Rafes! How about my second question above about child game objects getting despawed automatically? :)

    Also, a third question -- how fast are your OnSpawn/OnDespawn calls? i.e. is there any overhead due to reflection in using these?
     
  3. Rafes

    Rafes

    Joined:
    Jun 2, 2011
    Posts:
    764
    2nd Q: Just like in Unity's Destroy() method, the whole hierarchy is managed.
    3rd Q: They use Unity's SendMessage method to provide optional callbacks. So far I have never seen the overhead of this register. If you manage to get some crazy high-frequency behavior going where it actually does register as a performance issue, please let me know and we can look at an event-based alternative perhaps. In 4 years it hasn't come up though.
     
    Ghopper21 likes this.
  4. Ghopper21

    Ghopper21

    Joined:
    Aug 24, 2012
    Posts:
    170
    4th Q: I see you use Broadcast message for OnSpawned/Despawned -- does Broadcast message have any guaranteed order of invoking parent v. children? Empirically it seems parent first, but the Unity docs does not specify this, so I wonder if the order can be relied on. (This matters for a case I'm dealing with, where the parent subscribes to events on the child in its OnSpawn, while the child's OnSpawn clear's that event as part of its resetting logic. This would be fine if the children ran first, but not when the parent runs first. I can change the way I reset things, but this case prompts the above question which I'd like to understand in general.)
     
  5. Rafes

    Rafes

    Joined:
    Jun 2, 2011
    Posts:
    764
    No, BroadcastMessage doesn't guarantee order though you can implement a pattern where only 1 object receives the message and then manages the others. For example, it is common to have a script on the top of the prefab that has a field to drag-and-drop a child script reference, receive the message (implement the method callback) and then either process the child or run a method directly on the child. This way the prefab's top node is the user interface for that prefab and everything else is "internal" (nothing outside the prefab needs to have knowledge of the child, structure or behavior).
     
    Ghopper21 likes this.
  6. exiguous

    exiguous

    Joined:
    Nov 21, 2010
    Posts:
    1,217
    Hey Rafes,
    I hope you don't mind some suggestions for performance improvements and optimizations. I must say that I have purchased your Poolmanager long time ago but I currently don't use it since its too "overloaded" for my purpose. I run a bare bone custom implementation. But some things I did may also be usefull for your implementation.

    1. For Despawning you iterate over everything in worst case:
    Code (csharp):
    1.  
    2. // class SpawnPool
    3. public void Despawn(Transform instance)
    4. {// Find the item and despawn it
    5.    for (int i = 0; i < this._prefabPools.Count; i++)
    6.    // -> iterate over all pools
    7.    {
    8.      if (this._prefabPools[i]._spawned.Contains(instance))   // -> iterate over all elements in each pool
    9.  
    My "solution" to this is have a pool register an object with its spawn pool when its instantiated (not spawned!). The spawn pool keeps a dictionary where the Transform (or GameObject) is the key and the pool where its contained is the value. When an object shall be despawned you can find out the associated pool with an o(1) operation very quick. This registration can remain for the lifetime of the object and only needs to be removed when its destroyed before application is terminated. Also remember to set the initial dictionary capacity to a large amount to prevent useless resizing.

    2. List.Remove is shifting all objects. So when you delete the object at the beginning every object afterwards is copied to a new position for no real use.
    Code (csharp):
    1.  
    2. // class PrefabPool
    3. internal bool DespawnInstance(Transform xform, bool sendEventMessage)
    4. {
    5.    this._spawned.Remove(xform);
    6.    // -> List.Remove unnecessarily shifts all objects
    7. // -> also applies for opposite case with other list.
    8.  
    Since you (AFAIK) don't rely on the order of elements in the list use a smarter version:
    Code (csharp):
    1.  
    2. public static void RemoveAtFast<T> ( this IList<T> list, int index )   // -> extension method
    3. {// Fast version of the RemoveAt function. Overwrites the element at the specified index with the last element in the list, then removes the last element, thus lowering the inherent O(n) cost to O(1). Intended to be used on *unordered* lists only.
    4.    // author: José María Calvo Iglesias, source: http://extensionmethod.net/csharp/ilist-t/removeatfast
    5.    list[index] = list[list.Count - 1];
    6.    list.RemoveAt( list.Count - 1 );
    7. }
    8.  
    3. Indexing stuff with strings always makes me headache. AFAIK they also generate garbage. I prefer Enums instead. They can be iterated over (create a pool for each enum upfront eliminates runtime checking). They are fast. They utilize intellisense (ie Spawn(EnemyPoolEnum.Goblin) ) so you don't have to remember each string. And any typos are complained by the compiler (typesafe, no runtime checking). You could provide an empty enum where the user fills in a name for each prefab he wants to spawn. And this enum is then used to localize (index) the proper pool which should spawn it. For indexing the dictionary with an enum a custom comparer should be used since the default one uses boxing and is quite slow.

    I think the first 2 issues could speed up your implementation significantly with very little effort. The 3rd one is more a personal taste thing. Maybe hear what your customers say if they would prefer an enum based spawing (instead of string) which could also be used alongside your current method. They don't exclude each other but complement each other.
    That are just some thoughts. If you have further questions don't hesitate to ask but I'm not sure if/how these can be integrated into your package since I don't know in that detail like you do.
     
  7. Rafes

    Rafes

    Joined:
    Jun 2, 2011
    Posts:
    764
    Of course! We love feedback! I think support@path-o-logical.com is the best place for this so we can discuss some detail. Just a quick general response for anyone reading this. We will certainly review all suggestions. In the past when approaching some implementation details we have found that it made no measurable difference to performance, often we couldn't even get it to show when profiling a late-stage game. There is always a balance between the way Unity allows the presentation of configuration, stability and language quarks. I just don't want anyone reading this to think performance isn't a priority for us. After all, PoolManager has been used by a lot of projects over the last 4 years.

    Thanks again for taking the time to share ideas!
     
  8. Green-Jungle

    Green-Jungle

    Joined:
    Jun 10, 2014
    Posts:
    79
    I don't know and Don't understand why I get an errros as below images.
    I create :
    PoolManager.Pools[boxName].Spawn(spawnGameObject.transform, transform.position, Quaternion.identity);
    with boxName="Box" and then I create a GameObject which attach SpawnPool with name Box-Pool.
    Please help me.
     

    Attached Files:

  9. Rafes

    Rafes

    Joined:
    Jun 2, 2011
    Posts:
    764
  10. sevensails

    sevensails

    Joined:
    Aug 22, 2013
    Posts:
    483
    How does the ParticleSystems Auto Despawn works? It seems to be not working for my Particles.
     
  11. Rafes

    Rafes

    Joined:
    Jun 2, 2011
    Posts:
    764
    If you pass a particle system reference to Spawn() it runs an overloaded version of the method that starts a co-routine that listens for all particles to die and then despawns. Essentially is just
    1. Waits for the frame after the start delay ends
    2. Monitors IsAlive, including child-systems, as well as ActiveInHeierachy (in case the instance is despawned directly while particles are still alive)
    3. If the GameObject IS still active when the listener attempts to quit the system is cleared before despawning.

    There is also a maxParticleDespawnTime setting in the API as a safety maximum. This is currently set to 300 seconds, so if you have a very long running system that you want this feature for this may need to be set to a higher value, however, once a particle system runs this long you may wish to handle it in a custom way by using a transform with Spawn() and handling the despawn time-out yourself, depending on your game's needs.

    The most common issue I see is forgetting to pass particle system reference (using a transform instead). If you are sure the listener is being triggered you might want to throw a log message around line 1194 to print each frame while listening to see what is happening. Please email support@path-o-logical.com if you believe you have found a bug and I can help you more directly. You may need to submit a package that reproduces the issue as well unless code is enough.
     
  12. sevensails

    sevensails

    Joined:
    Aug 22, 2013
    Posts:
    483
    I cannot build my project on Unity 5.4.

    Code (csharp):
    1.  
    2. Error building Player: GetComponentFastPath is not allowed to be called during serialization, call it from Awake or Start instead. Called from script 'SpawnPool' on game object 'CameraBoard'.
    3. See "Script Serialization" page in the Unity Manual for further details.
    4.  
     
  13. Rafes

    Rafes

    Joined:
    Jun 2, 2011
    Posts:
    764
    Hi,

    I've had some trouble with installing the beta copy but I was assured by Unity that these are only warnings in 5.4 and will not affect any functionality. Are you sure this is blocking your build? I will report the issue immediately. Please email me the details at support@path-o-logical.com. Include your exact Unity version, OS and this error again.

    Cheers,
     
  14. sevensails

    sevensails

    Joined:
    Aug 22, 2013
    Posts:
    483
    On first Try the Builds always fails. But on second try it works!

    Unity 5.4.0b10. Windows 10 14291.rs1_release.100.141-2254
     
  15. luispedrofonseca

    luispedrofonseca

    Joined:
    Aug 29, 2012
    Posts:
    843
    @Rafes Can you please fix the warnings in Unity 5.4?
     
  16. ury2ok2000

    ury2ok2000

    Joined:
    Dec 29, 2012
    Posts:
    46
    Hello I'm using poolmanager however I hav noticed something off. I preload 100 objects. During game play the values of the objects are changed and in some cases I add children to those objects. My problem is when the objects are destroyed and then spawned on again later they still have those values set and the child objects still. Am I doing something wrong. I really just want it to spawn the prefab as it is initially setup, as if it is just instanced into the game.
     
  17. NioFox

    NioFox

    Joined:
    Dec 28, 2012
    Posts:
    65
    Deleting the functions that generate the warnings worked for me.
     
  18. silentneedle

    silentneedle

    Joined:
    Mar 14, 2013
    Posts:
    280
    You probably need to implement that by yourself.
     
  19. GenPhi

    GenPhi

    Joined:
    Dec 27, 2014
    Posts:
    11
    Thinking about purchasing but noticed that they've been dead on updating and on their website. Still worth the purchase or should I move on? Thanks...
     
  20. jrDev

    jrDev

    Joined:
    Nov 5, 2008
    Posts:
    1,700
    Hey,

    I downloaded it into a new project today for Unity 5.6 and it works perfectly fine.

    Thanks,
    jrDev
     
  21. GenPhi

    GenPhi

    Joined:
    Dec 27, 2014
    Posts:
    11

    Thanks for the reply! I guess what I was really asking is if the asset is dead (no plans to update) or are there updates planned.
     
unityunity