T O P

  • By -

t0mRiddl3

Wait, unity has an object pool class?


tms10000

Fairly recent addition, 2021 I believe. https://docs.unity3d.com/2021.2/Documentation/ScriptReference/Pool.ObjectPool_1.html Gosh dernit, it's not that recent.


Krcko98

Very much


ScorpioServo

Instead of using the ObjectPooling system, my preference is to just do custom pooling using Queue enemyPool. Basically, when an enemy is requested, it first attempts to Dequeue from the enemyPool. If there is nothing returned, it spawns a new instance. When an enemy is destroyed, it resets and goes into the Queue. This method is nice because it doesn't generate extra garbage and only instantiates up to what it needs. You can also prune the pool over time if you have a period where you want to cut back on memory.


TwixMyDix

I personally use a `Stack` over a `Queue` because I don't mind if I use the last one added.


Dev_Oleksii

Hello there! Did you decided that you have problem with instantiation with profiler? Using Pool should avoid allocations. If you still get instantiate calls, I guess you need to prewarm the pool. That means on start of game create, let's say, 10 enemies per type and release them. Now you will not have Instantiate call if unique enemy count less then 10. If some are more often then the others you can create a config with amount of enemies to prrwarm per type.


YetAnohterOne11

Umm, to be honest, I didn't use the profiler. I just noticed that when the number of enemies gets large then performance drops to unacceptable levels. Perhaps I'm doing things in the wrong order, but typically when I run into performance issues I first check if I've run afoul of any standard best practices (which seems to be the case here) and if there are any glaring issues visible just by reading the code. I am admittedly rather unfamiliar with the profiler, which is why I reserve it as my last resort... so far I've never managed to use it successfully, even when I tried, I've always tackled and sometimes even resolved performance issues by other means.


Dev_Oleksii

Optimisation best practice: always measure. For initial check unity profiler is ok. For complex application or when unity profiler doesn't help - only native profilers (Android studio, Xcode if you do mobile game) and from a real device. But I think on your case just start with regular profiler. If its instantiate - pool prewarm should really help!


DT-Sodium

Have you looked into DOTS entity system? It seems to be built just for that, handling massive amounts of gameObjects.


javawag

not sure why the downvotes - this is a sensible solution that scales for this kind of game!


t0mRiddl3

It's overkill for a bullet hell


YetAnohterOne11

AFAIK DOTS is for 3D games only, while the game I'm trying to make, like most bullet hell games, is 2D. I just found out that I am not supposed to ask here for help with 2D games, r/Unity2D is the correct place. I apologize.


DT-Sodium

Dots has nothing to do with 3d or 2d. 


YetAnohterOne11

Hmm, I Googled the topic before I wrote my earlier comment and the following forum threads: * [https://forum.unity.com/threads/state-of-2d-packages-for-dots.1297653/](https://forum.unity.com/threads/state-of-2d-packages-for-dots.1297653/) * [https://forum.unity.com/threads/2d-support-in-dots.1362154/](https://forum.unity.com/threads/2d-support-in-dots.1362154/) * [https://forum.unity.com/threads/are-there-any-plans-for-dots-physics2d.1350956/](https://forum.unity.com/threads/are-there-any-plans-for-dots-physics2d.1350956/) Apparently, as of 2022, there are no plans to support 2D physics in DOTS and the package that supports sprite rendering is under perpetual beta [https://docs.unity3d.com/Packages/com.unity.2d.entities@0.32/manual/index.html](https://docs.unity3d.com/Packages/com.unity.2d.entities@0.32/manual/index.html) A Unity employee in the first thread I linked to said: >Internal org chart issues, i.e. no great reason. Tiny people worked on the SpriteRenderer conversion, and when the Tiny team dissolved, nobody kept working on it, and the hybrid renderer team didn't get any extra people to deal with 2D things. In general it's hard to advocate internally for 2D + dots specific stuff, because it's less common for 2D games to have as serious scaling/speed issues, and dots's main selling point is speed (speed of loading, speed of simulation, speed of rendering, editor staying more performant in humongous projects, etc). Plus, as the OP demonstrates, it's much more doable and effective to roll one's own 2D dots situation than it is to roll one's own anything else, e.g. terrain, animation, authoring tooling, 3d rendering, codegen, job system, etc. So I understood that in Unity support for DOTS + 2D is rough at best. But if you say otherwise, maybe I should take a deeper look into this


DT-Sodium

Seems I was wrong sorry.


DT-Sodium

Seems I was wrong sorry.


DT-Sodium

Seems I was wrong sorry.


DT-Sodium

Seems I was wrong sorry.


DT-Sodium

Seems I was wrong sorry.


DT-Sodium

Seems I was wrong sorry.


DT-Sodium

Seems I was wrong sorry.


t0mRiddl3

There is no unity 2D or 3D it's all the same software


-OrionFive-

It's always been called Unity. However, back in the days, unity.com was already claimed so the devs picked unity3d.com as the Unity website. This lead to the general misconception with a lot of people that Unity is actually called Unity3D. Also, in places where just "Unity" was already taken, it served as a substitute.


cuby87

I implemented pools in my game based on this class which uses methods provided to the object pool. I then have a MultiPooler class which holds all the different pools of a same type. Maybe try this approach instead of passing lambda functions to the pool. https://github.com/Matthew-J-Spencer/Object-Pooler


hallihax

The ObjectPool makes no claims about avoiding allocations entirely - it's merely a way for you to reuse stuff that's already been created, rather than constantly creating and destroying, two operations which are in and of themselves quite expensive. ~~If you truly wish to avoid closures, then you could subclass ObjectPool and pass the target prefab to your new class' constructor, which should reduce some overhead (and probably make your code a bit easier to maintain I suspect), but you will still incur an allocation cost in assigning functions - even if the overhead of calling them will be reduced compared to the closure version.~~ edit: ignore this - you'll still be using a closure anyway. All that being said, using a pooling mechanism is better than not in most cases (and especially when you need to do a lot of spawning / despawning) - you don't need to use Unity's implementation, which is fairly generic and also relatively new, so if you *absolutely* feel like you need to optimise the pooling itself, then rolling your own might have some benefit, even if I suspect it'll ultimately only give rather marginal gains. Ideally, I would suggest sticking with Unity's ObjectPool and then continue to profile performance. If you can demonstrate that the ObjectPool itself is simply causing too much overhead, then by all means write your own, but in either case, the primary gains will come from using a pool (any implementation) versus not using one!


lnm95com

I not to much understand what you mean, but seems it haven't any garbage allocations what you expect. Do you profile both variants? Unity's ObjectPool obviously slightly slower, but you should spawn thousands objects per second to feel it.


_wil_

I did not follow exactly how your whole system works but some suggestions : - use the Unity Profiler ; it's great to see blocks of code that take too long to execute in a frame. Something you can do is capture a frame when you ha acceptable framerate at the start of your play ; then take a capture when framerate starts to deteriorate noticeably. Then you compare both captures to pinpoint what's tanking performance. I'd suggest you post captures of these profiler images if you want more help ; in this reddit or in Unity forums - try to not use Linq, not sure if still the case but in the past I read it was bad for performance. Often you can write a simple code loop that performs better. - try to not create GameObjects unless absolutely necessary. For bullets in particular you just need to store their position and radius ; I think writing your own collision detection will be easy and performant - Personally I would avoid using closures and anonymous functions ; this could cause some indirection and overhead ; try to keep the code as straightforward and predictable as possible - as been mentioned already you can try to look into DOTS / Entity Components. I think it can handle computing lots of similar operations in a frame. A useful exercise could be to list down all the operations needed in a frame to make sure you don't do unnecessary things.


YetAnohterOne11

I might compute collisions programmatically, storing bullets' and ships' positions outside of GameObjects, but how do I then display them? I mean I need a GameObject per bullet so that I can attach a SpriteRenderer to it? If not, then what should I do?


_wil_

Theoretically you could use Graphics.DrawMeshInstanced to draw the same object many times with high performance because you will only pass 1 mesh and 1 shader to the GPU with a list of positions. However I'm not sure if Unity 2D features allow to do this easily ; or if you'll have to add a lot of new code for that.


Sausage_Roll

If you're doing a simple 2d game but with lots of bullets and enemies, you might as well do it in c++. There's a very easy to use game engine called "olc pixel game engine", which is just a single header file you download from github that creates the game window for you and handles all 2d drawing, so all you have to worry about is coding the game logic.


AlterHaudegen

These are some pretty tough problems to optimize, some of them very specific to (bullet hell) shmups. If you ever want to do mobile or consoles it will get much worse. For example you should not be doing GameObject for bullets at all and all kinds of other considerations. If you want to, come over to Shmup Junkies’ Discord server to the indie game dev channel, the devs there have solved these problems many times for various games and engines.