My long term goal is to create an asteroid game that allows per pixel terrain destruction.
First attempt was to create a tight polygon collider around the asteroid shape and update it dynamically. It worked pretty well but failed on some specific edge cases and always felt messy:
Second and current attempt uses a basic Quadtree implementation to build a set of box colliders that fill in the texture. I’m pretty happy with the code, and aside from major editor lag if the game object with the colliders is selected, performs pretty well even during terrain destruction:
However it slows to an absolute crawl when I try to rotate the game object due to the physics calculations on all of those colliders. Given that rotation is necessary for what I’m working toward, I’ve come here looking for advice.
Can anyone suggest a way to modify the Quadtree approach in a way that could remove or mitigate the performance impact of rotation?
If the Quadtree approach isn’t salvageable due to the large number of colliders, is there any promise in the polygon collider approach?
Obviously both approaches have weaknesses, so can anyone suggest a different approach that might accomplish the same goal?
Also happy to take any advice or comment on the code itself. I’m about 6 months into learning Unity and C# so I’m sure there are some newbie mistakes or bad habits in there! This is a follow up to my first post I made here back in February.
I think anytime you rotate or move non-Rigidbody colliders, they ALL get destroyed and recreated that frame.
This might explain your absolute crawl problem.
I just tried with a 16x16 sprite dude and even that is chuggy.
At the end of the day Unity and the physics system isn’t optimized to model grids with this much detail.
You might get somewhere with modeling the actual physics collider as some kind of rubberband-wrapped simple polygon, but then do your own collision just for the character to tunnel into the asteroid.
As Rusty Schweickart explained in his Long Now presentation back in 2004 (!!!), asteroids are called “rubble piles” so you could always say after you tunnel in and climb back out, well, it just caves in and collapses back down to a more simple polygon shape.
if you want to do per pixel destruction, unity is a poor choice of engine, go check a game called “noita” and see how they handled things (its not made in unity)
Not really, using Box2D is a poor choice for pixel orientated physics but not Unity as a whole. You can absolutely implement this.
I took a quick look at your script and the reason why it’s awful performance is that a single asteroid is composed of around 500 BoxCollider2D and you are modifying the Transform.
The technique you’re looking for is to not model all those colliders per-pixel for no reason. You can create an outline until you collide. When you collide, you carve out or decompose what you need. I’ve seen plenty of implementations of this that does use the 2D physics. Sopme of those used the CustomCollider2D which gives you direct access to the shapes used by physics.
If however you’re trying to model each and every pixel then no, the stock 2D physics perhaps isn’t for you.
To illustrate the use of the CustomCollider2D and creating primitive shapes rather than colliders, I quickly changed your code to use a single CustomCollider2D and changed your implementation to create a PhysicsShapeGroup2D then just assign it and I’m seeing 400fps rotating it (slightly less in the video as it’s capturing). Previously I was getting 1fps. This is still with 500 polygon box shapes.
i just dont see the features for per pixel destruction, if you use texture2D its too consuming to keep doing apply(), if you modify terrain you have to recalculate the whole collider
Just doesnt seem easy to just put a pixel on the screen, to draw a line of pixels for example is also an insane challenge, I have seen someone post an insane shader just to tackle creating a line of pixels
just seemed that it doesnt fit the use case of granularity of “per pixel” logic
True but also look at the users code, a small change made their prototype work. It all depends on the scale. My main point here is that it’s not about the limitation of rotating, it’s about when doing things at scale, you have to understand what you’re doing and use the profiler.
My other point was that whilst 2D physics might not be appropriate, this doesn’t mean you cannot use Unity to achieve this. In the end, it’s a generic game engine but a debate on what people think isn’t what the OP wants I guess.
The reason for the hiccups is because the quad-tree you’ve implemented is pretty slow and can be improved drastically. There’s no reason why it couldn’t be way below sub-millisecond, especially if you use the job-system for this and maybe a different structure like a BVH which can be reduced to a single array. Look at the DOTS physics broadphase for inspiration here.
As mentioned above though, it’s not exactly a great approach to the problem and there’ll be all sorts of hurdles along the way including updating the textures etc. Other issues can be that generating/changing so many shapes can cause the physics system to suddenly have to calculate a lot of potential contacts which takes times. You can get around that by changing the shapes gradually over several simulation steps i.e. spread the changes over time. I think this is part of the issues you’ll have.
An alternative still using 2D physics is to use the latest 2023 Unity release and the CompositeCollider2D which allows you to perform geometry operations thus allowing you to merge, subtract (etc) colliders so your project would have a single outline for the asteroid and you could subtract the circle from it in one operation like this:
Still, operations at the pixel scale mean you’ve got to be very careful.
Big thanks for the suggestions, this is exactly what I was looking for. I’m well aware that I may end up having to scrap my approach completely later on, but as long as I learn more on the way then it’s all good. A few months ago I had no idea what a quadtree was, so it’s all part of the process.