Search Unity

[Released] Pool Boss - super easy pooling solution.

Discussion in 'Assets and Asset Store' started by jerotas, Oct 20, 2014.

  1. Yukichu

    Yukichu

    Joined:
    Apr 2, 2013
    Posts:
    420
    Forum could be the work firewall killing me, not a big deal.

    I know having to instantiate more will cause some performance issues depending on how many you do, but... think of it like, okay, I want to pool 1000 damage messages. Oh hey I have a few more people playing, awesome. Oh snap, we're going to use 1200 damage messages. So basically, you're saying that the extra 200 will just keep getting instantiated/destroyed until I'm below 1000, all because my best-guess was incorrect. I can't always know the static limit in every use case, but yes we can all best-guess. I'd rather when I hit 1000 pooled items used, the pool grow by 20 and then when I hit 1020, grow by 20, etc. or by 50... just grow as needed. I guess I could say, 'Okay, pool some ridiculous number so I never need to worry about it' but pooling 5000 objects vs.1000 just seems... weird.

    I wouldn't call it a 'bell and whistle' really. It's a good feature I think. You and I both know it isn't terribly difficult to set up, which is why I'm confused why it just isn't there. I've written my own pooling classes for like 10 different things, and finally I was like, fine fine I'll check out the boss of pooling so I can stop making pools of junk and was disappointed by no dynamic growth settings.

    It's cool if this is just how you want it I guess. I'll just go back to making pool #11, 12, 13, etc.
     
  2. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I think you misunderstand how the "Instantiate More" part works. It does Instantiate new pool items when you've reached your preload limit and need a new one, yes. But Pool Boss *never* calls Destroy. These new Instantiated pool items are then "in the pool" and despawned and spawned from then on. So basically the pool grows by one item every time this happens, unless it reaches your item limit, in which case it won't even Instantiate one.

    You're also free to just put a ridiculously high number into the Item Limit if you don't have a good best guess. It won't really harm anything.

    So I think this system still works for what you want to do. It's just a slightly different set of a couple fields than what you're used to.
     
    Last edited: Mar 31, 2015
  3. electroflame

    electroflame

    Joined:
    May 7, 2014
    Posts:
    177
    I've got a rather interesting problem that seems to stem from Pool Boss appending "(Clone #)" to the end of item names.

    It seems like, after some time, Pool Boss will simply stop respawning items due to it not thinking it's in the Pool. If I enable the feature to let it create items automatically, it'll make a new one, but it'll be called "Item (Clone #) (Clone #)". Each time it makes a new one, it'll add another "(Clone #)" to the end of the name.

    This line of code in PoolBoss.cs seems to be creating the Clone suffix:
    Code (CSharp):
    1. createdObjTransform.name = prefabTrans.name +" (Clone " + cloneNumber + ")"; // don't want the "(Clone)" suffix.
    (Line 99)

    If I comment out everything after prefabTrans.name, it works fine. I'm kind of confused why the comment says "don't want the (Clone) suffix" when that line of code actually is adding the (Clone #) suffix!

    Alternatively, it looks like it what would also work would be to modify this line...
    Code (CSharp):
    1. var itemName = transToSpawn.name;
    (Line 205)
    ...to remove any (Clone) suffix from the name.

    I'm not quite sure what's going on, any thoughts?

    EDIT: Adding this bit of code after the last line I mentioned also fixes the problem (but doing string operations in every Spawn call seems like a very, very bad idea).

    Code (CSharp):
    1. int index = itemName.IndexOf(" (Clone");
    2. if (index > 0)
    3.     itemName = itemName.Substring(0, index);
    There's definitely something funky going on with the suffixes, but I'm not sure if the suffixes are intentional or not.
     
    Last edited: Apr 3, 2015
  4. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    The suffixes are intentional. It's no good to have 30 objects floating around with the exact same name when you're trying to debug what one of them is doing, so we give them a unique name (Pool Manager does this as well I believe). I can't think of a better way to do it other than string operations.

    You mentioned a lot of code there, but I'm not sure how to reproduce the bug you saw or what your exact fix was. I've definitely never seen the bug and no one has reported it before now. Please give a concise summary and I'll see if I can reproduce / fix it.

    Thanks!
     
  5. electroflame

    electroflame

    Joined:
    May 7, 2014
    Posts:
    177
    I'm not sure if this'll help, but this is where I'm seeing the bug:

    1. I've added an item to the pool that should only ever have 1 item.
    2. On startup, I immediately spawn the item using PoolBoss.SpawnInPool. Whether it's the Transform or String version doesn't appear to matter.
    3. I despawn the item (using PoolBoss).
    4. When I try to respawn it (using PoolBoss.SpawnInPool) it fails, telling me the item (with Clone in it's name) is not set up in PoolBoss. Again, if I remove Clone from the object's name (manually even, once the game's running) it respawns fine.

    EDIT: The only fix I've found is to either remove suffixes entirely, or use that last bit of code I posted when getting the itemName in the Spawn method. The last bit of code strips any stray Clone suffixes from the itemName, but it's also doing string operations every time you try to spawn something -- probably not the best.
     
  6. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I made code so I have 2 buttons. 1 to spawn the item, and 1 to despawn it. There's only 1 of that pool item in the pool.

    I can click button1, then button2, then button 1, then button 2, forever, and I'm not seeing any problems. So I'll need different instructions. Still can't reproduce any problem.

    As you say, string operations during spawn are not the best, however we need to maintain a unique name for each. It's a worthy tradeoff during debugging, trust me.
     
  7. electroflame

    electroflame

    Joined:
    May 7, 2014
    Posts:
    177
    Yeah, I'm not really looking to get rid of the suffixes, I'm just not sure what the deal is.

    It looks like the issue stems from caching the despawning transform to respawn it later. If I do this:

    1. Throw my transform into a list to respawn it later
    2. Despawn it
    3. Respawn it after a couple of seconds, by passing back in my stored transform, I have the issue.

    Currently I'm taking my stored transform's name and stripping it of any suffixes before passing it to the spawn method. This actually works pretty well, and I could probably live with it since it's only doing string operations when respawning.
     
  8. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Oh, ok. That's actually a usage I never considered. I would consider it incorrect usage. Normally the transform you pass to Spawn would be a "reference Transform" and not an actual spawned-before-object, so it shouldn't have a " (Clone" in the name. Anyway, your fix of the string check fixes it, so I will add that to the code for the next version.

    Thanks,
    -Brian
     
  9. electroflame

    electroflame

    Joined:
    May 7, 2014
    Posts:
    177
    Awesome, thanks! The only reason I don't use a "reference Transform" is because this is a generic script and I may or may not know what I'm spawning.

    I could probably refactor it, but it seems alright for right now. I also don't think the string operations will become a garbage issue if it's called as infrequently as respawning (on the few items that'll end up using automatic respawning).

    Sorry about that, it didn't even occur to me that it was the cached Transform that was the issue.
     
  10. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    No problem! Thanks for being patient.
     
  11. electroflame

    electroflame

    Joined:
    May 7, 2014
    Posts:
    177
    Sorry if I'm being annoying, but I've got something else I wanted to ask about.

    Whenever you spawn or despawn an object with PoolBoss, one of the things that you call is your SetParent method. Up until this point I've never had a problem with it, but tonight it's giving me a bit of trouble.

    Some background:
    I've got an (admittedly, probably not common) object hierarchy that looks like this:
    • Empty Object (that I use to correct the children's rotation)
      • The main object (that handles all logic, and also has the mesh renderer and colliders).
    The issue stems from PoolBoss reassigning the parent to the PoolBoss object, so on a despawn/respawn the "main object" gets deparented from my Empty Object.

    Currently I seem to have fixed it by just changing the SetParent's Unity 5 block to this...
    Code (CSharp):
    1. if (trns.parent == null)
    2.        {
    3.             var rectTrans = trns.GetComponent<RectTransform>();
    4.             if (rectTrans != null)
    5.             {
    6.                 rectTrans.SetParent(parentTrans);
    7.             }
    8.             else
    9.             {
    10.                 trns.parent = parentTrans;
    11.             }
    12.         }
    ...with the null check being the bit I added. Pretty much it just checks if the parent isn't already set to something before resetting it, but I'm curious if you think this will cause problems later, as you have a better understanding of the asset than I do.

    I realize that I'm pretty much coming up with crazy use-cases that you probably haven't accounted for, so I apologize in advance if this seems aggressively stupid.
     
  12. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    That's not really a rare scenario. Doing rotation animations in Unity pretty much requires it. I work with Pool Boss with prefabs like that all the time. What I believe you're "not doing right" is you should be spawning and despawning the empty object, not the child. That means changing your code so that any code on the child that needs to despawn it, instead despawns the parent.
     
  13. electroflame

    electroflame

    Joined:
    May 7, 2014
    Posts:
    177
    Hm, alright. It's more of a general system, so I'll have to add a per-object option on whether to despawn the object or the parent.

    Shouldn't be too difficult, thanks for getting back to me!
     
  14. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    No problem!
     
  15. jalapen0

    jalapen0

    Joined:
    Feb 20, 2013
    Posts:
    136
    Hey small warning in 5.1.

    Parent of RectTransform is being set with parent property. Consider using the SetParent method instead, with the worldPositionStays argument set to false. This will retain local orientation and scale rather than world orientation and scale, which can prevent common UI scaling issues.
    UnityEngine.Transform:set_parent(Transform)
    PoolBoss:SetParent(Transform, Transform) (at Assets/DarkTonic/PoolBoss/Scripts/PoolBoss.cs:291)
    PoolBoss:InstantiateForPool(Transform, Int32) (at Assets/DarkTonic/PoolBoss/Scripts/PoolBoss.cs:101)
    PoolBoss:Awake() (at Assets/DarkTonic/PoolBoss/Scripts/PoolBoss.cs:79)
     
  16. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Thanks, I'll take a look.
     
  17. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    Hey Brian

    Is there a convenient way to check if a transform instance exists in the pool?

    cheers

    Nalin
     
  18. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Are you looking for a code way to check? Please clarify and I'll get back to you.
     
  19. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    Yes please:)

    Essentially I want to check whether an item is in the Pool Boss before I delete it as it saves getting the error message later.
     
  20. Korindian

    Korindian

    Joined:
    Jun 25, 2013
    Posts:
    584
    Hi,

    I have PoolBoss as part of Core Gamekit. I'm looking to be able to pool objects by creating the pool through scripting at runtime as well as adding prefabs to it at runtime, as data about which prefabs (out of many) to use will be loaded from the filesystem after the scene starts.

    After looking at the API, I don't see a way to be able to create or add to pools at runtime. I understand that you did not include features that you don't think are necessary, and I have another pooling asset which supports this functionality, but I would prefer to use Pool Boss as I know you have great customer support, you continuously update your assets, and I like the way you have the spawn count displayed in the inspector for each item.

    Is there already a way to do this that I'm missing? If not, would you consider adding the ability to set up a pooled item and set all its options (like preload quantity, allow instantiate more, item limit, log messages, etc.) at runtime through scripting?
    Thanks.
     
  21. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Use this:

    Code (csharp):
    1.  
    2. if (PoolBoss.PoolItemInfoByName("myPrefabName") !=null)
    3.  
    4. {
    5.  
    6. // exists in pool!
    7.  
    8. }
    9.  
    10. else
    11.  
    12. {
    13.  
    14. // doesn't exist in pool
    15.  
    16. }
    17.  
    18.  
     
  22. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I will be adding this only as part of Core GameKit, not Pool Boss. Watch for the next update.

    Thanks!
     
  23. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    Hi Brian

    Unfortunately this does not work.

    What I am trying to do is find out if (transform.name) is in the pool and it has a name of "PrefabName (Clone x)" and in this case the above code always returns false (i.e. not in the pool) when I tested it :(

    N
     
  24. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    yeah, you're supposed to chop off the (Clone X) part. I'll fix this in the next version. Submitted a new version last night.
     
  25. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    hmmm

    actually what I am after is to find whether the instance itself (not the prefab) is in the pool.

    Is there any way to do that?

    N
     
  26. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    No. I'm still not sure why this is useful information?
     
  27. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    It's useful to me so that I can prepare a scene without setting up PoolBoss in the first instance, where I can remove a game object by using Destroy(). Then if I add PoolBoss later it can be seamless because I can use PoolBoss.Despawn().

    Hope this makes sense.
     
  28. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Yes, I understand what you're saying now, thanks for the clarification.

    I'm questioning why you'd want to go the trouble of writing that code (if the API existed) instead of just setting up Pool Boss in that other Scene too? It's certainly not something we'd ever use, and no one has asked for it before...

    Destroy is bad for performance, I'm sure you know.
     
  29. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    It was only for rapid prototyping in the first instance before setting up pool boss. It also means I can re-use elements in a scene where they exist in the beginning as opposed to being spawned.
     
  30. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I would suggest that you simple check the "auto-add missing items" checkbox in Pool Boss and don't set up any items. That's what it's for.
     
  31. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Master Audio and Core GameKit are now on sale for half off! Pool Boss is also FREE for a few days, so grab it while you can!
     
  32. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    Cheers Brian, have posted on uFrame Slack
     
  33. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Not sure what that is or why it's a good idea? Thanks
     
  34. puzzlekings

    puzzlekings

    Joined:
    Sep 6, 2012
    Posts:
    404
    I previously did a youtube tutorial showing how to use PoolBoss with uFrame



    A lot of the uFrame users hangout on their Slack forums :)
     
    jerotas likes this.
  35. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Pool Boss V 1.0.8 is submitted! Changelog:

    - Updated to newest version of Pool Boss in Core GameKit. Now includes categories and more debugging tools!
     
  36. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Master Audio is part of the madness sale starting today and running through June 3rd! It's 60% off, for only $18. Perfect time to grab multiple copies as it hasn't been this inexpensive for over a year.

    Our other plugins Core GameKit and Pool Boss are also 60% off "just because". Have a great week!

    -All at DT.
     
    Last edited: May 23, 2016
    99thmonkey likes this.
  37. Shadeless

    Shadeless

    Joined:
    Jul 22, 2013
    Posts:
    136
    @jerotas
    Hey, so I got Pool Boss and the way I want to use it is to get the prefab that is going to be spawned before it get's spawned so I can configure it before OnSpawned is called.

    So something like:

    Transform GetNextItemToSpawn(Transform transformToSpawn)

    So then I can use this method to get the item before it's spawned and I can GetComponent on it and set it up. And afterwards I can use PoolBoss.Spawn().

    I looked through the code and it seems like you're using Random.Range to get a randomIndex to spawn. Is there a good reason to do this? If it wasn't random the GetNextItemToSpawn could be implemented easily by always returning the 0 index lets say.

    I'm interested to hear your opinion.
    Cheers :)
     
  38. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I put the randomness in there just so each clone would be used as often as the others. Not strictly necessary.

    I was thinking about putting each pool item into a Stack and just using the top item when I have time. It would supposedly execute faster.

    If by "set it up" you mean add components, I believe that will work. But you won't be able to call any methods on the disabled game object.

    I have never encountered a scenario where you couldn't do what is necessary through OnSpawned and OnDespawned alone. What is it you're trying to do?
     
  39. Shadeless

    Shadeless

    Joined:
    Jul 22, 2013
    Posts:
    136
    Ok so I'll present a simple scenario.

    Let's say I have prefabs which have a CircleCollider2D and I have a pool of them.
    So let's say I want to Spawn one of these but I also want to set the collider.radius to a value I want before OnSpawned is called.

    I just need to be able to get the item that's about to be spawned before OnSpawned is called, that's it.
     
  40. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Ok. What would fail to work properly if you set the radius in OnSpawned? A trigger or collision event would still happen when you changed the radius there...
     
  41. Shadeless

    Shadeless

    Joined:
    Jul 22, 2013
    Posts:
    136
    It was just a simple example of what I need to do. In my case I need to set up the ParticleSystem in OnSpawned and then call Emit(). But before that I need to pass a value to the script.

    This is what it would look like.

    1. PoolBoss.GetNextItemToSpawn(name).GetComponent<Script>().scalarValue = value;
    2. PoolBoss.Spawn(name);
    3. OnSpawned gets called and uses the scalar value which I passed to set up the ParticleSystem and call Emit().
     
  42. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    That's one way to do it. I personally wouldn't do it that way.

    The code that sets the ScalarValue could be in OnSpawned and look up what it needs to set the scalarValue to from elsewhere (possibly a static method that holding a list of these values) prior to doing Emit().

    By the way, if you're using the full Core GameKit, you can access the item about to be spawned before it's spawned in the Spawner classes (creating a subclass) and also from Prefab Pool class if you use those, even though it's a random index in both cases.

    Anyway, I'll put on the roadmap to have a way to get "next pool item"
     
    Last edited: May 25, 2016
  43. brettj

    brettj

    Joined:
    Feb 9, 2015
    Posts:
    43
    Is there a simple way to create a new category in code?
     
  44. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    I could probably hack something together, but why is that useful? You don't create pool items at runtime, right?
     
  45. brettj

    brettj

    Joined:
    Feb 9, 2015
    Posts:
    43
    Yeah, I like to create pools in the code (at Awake) so everything is being set up in one place. And that's no trouble right now. But doing it this way I don't get the benefit of despawning a category, which would be nice.

    Is there a performance difference in creating pools this way in code vs in the editor? They're both instantiated in Awake or Start I would assume.
     
  46. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Everything is created in Awake. If your categories aren't going to be decided dynamically, you can just create the Categories with no items in them using the UI.
     
  47. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    Sale is over, back to normal price of $9.95
     
  48. MythicalCity

    MythicalCity

    Joined:
    Feb 10, 2011
    Posts:
    420
    Hi, does the pool boss have a way to do pooling in Unity Networking (unet) object instantiation?
     
  49. jerotas

    jerotas

    Joined:
    Sep 4, 2011
    Posts:
    5,572
    No, and there's no pooling plugin that does have that capability currently.

    We may have Photon integration first (since we use that), before unet, but it may be awhile.
     
  50. Shadeless

    Shadeless

    Joined:
    Jul 22, 2013
    Posts:
    136
    @jerotas

    Hey, so I'm getting the need again to get the item that's about to be spawned before I call Spawn. You mentioned using a Stack to get items and this would be really nice.

    It would be great if you could make it work this way. The Random.Range thing is really pointless and with a Stack you can Peek at the top item so you can add the GetNextItemToSpawn function.

    Cheers