Hello.
I am wondering how exactly is the collision between calculated between all the game objects in the scene?
I implemented a tile map ( basically a tile is a game object that either has a normal collider if its unpassable or has a trigger collider, that’s sets the tile position of the player, if its passable ).
So with my 20 x 15 tilemap, my scene has at least 300 colliders.
Surely unity won’t calculate the collision between all these colliders, but know which game objects make sense for collision check ( tiles of course aren’t moving, just the player ).
Can you tell me roughly how it’s done internally? Everything seems fine performancewise, if I keep adding game objects and colliders and have a very big scene, colliders that are far away from the player will be ignored, right?
Thanks in advance.
You wouldn’t use physics colliders for a tilemap; that’s highly inefficient if all you need is passable/not passable. The more colliders you add the slower it all goes. Implement a 2D boolean array for that and check the array instead. Using separate GameObjects for tiles is inefficient as well.
–Eric
Passable and impassable is not all I need. Tiles can also be destroyed ( not in the actual object destroying way ), so impassable tiles become passable and they may have an object on top of them ( so they become impassable ).
I know there are way more efficient ways of doing this, most people talk about meshes in regard to tilemaps, but I’m not quite there yet.
But let’s say I have a game like super mario, where you walk from left to right. When the player is on the far right on the scene ( the map), will the game objects ( or its colliders ) on the left of the map still have a noticable impact on the game regarding the performance?
Is it better to implement my own collision logic? It’s not that easy in unity as it was when I was programming in java, because of the different unit systems ( world points, screen points… ). Yet I managed to generate my tilemap out of gameobjects that are 40px in size. I thought not having to implement all stuff on my own was the point of unity, but I get that there are use cases, where it doesn’t make sense to rely on unity’s physics engine for example.
In java I knew exactly which tiles to check for collision, so with every move there were only 3 tiles to check the collision with. That’s why I’m asking, but since the player is the only thing moving, isn’t unity disregarding most of the tiles ( gameobjects ) for collision detection? Checking the players collision with every tile on the screen would be a huge calculation each frame. ![]()
That’s still just passable/not passable, and doesn’t need physics.
Yes. e.g., all active GameObjects need to be culled for rendering, which takes time.
If you don’t actually need physics (gravity, movement, friction, etc.), then yes. It doesn’t necessarily check every object for collision (using some kind of spatial optimization), but nevertheless e.g. 10,000 objects is slower than 10 objects. If you don’t use physics, but rather an array, then you eliminate all of that unnecessary overhead, and for the most part the number of tiles doesn’t matter.
–Eric
I’m basically just using the physics engine for the collision. I don’t have gravity ( since its a topdown game… ) and the player has a constant velocity when moving ( the velocity is also instant ), so I am technically also using the physics engine for movement ( not just changing the players position, because I want the player to react to colliders, therefore I am using the rigidbodys velocity
I am generating the tile map with a 2 dimensional array, so I can easily get each tile with it’s x and y, but each tile is a gameobject…
Writing my own collision detection is more difficult than it was in java, since I have to translate between the world and screen points, but maybe I will give it a try. For this game 20x15 is about the final size of the tile map, so maybe it will also run with decent fps with my non-performant solution. I know it’s highly inefficient considering its a tilemap. But the number of colliders ( >=300 ) etc. could be in a non-tilemap, right?
EDIT: Another idea of mine was to enable only the colliders of gameobjects that make sense for collision, for example when moving up, the tile above the player makes sense to check the collision with. I don’t know if the enabling/disabling overhead is more efficient than what unity does internally to improve performance with the colliders.
I could also disable the renderer of a tile, if it is not visible ( for example if the tilemap is bigger than the viewport ). Naively in my opinion this would be very performant, since you will only check collision with gameobjects that you need to.
Or I could manually check the collision ( still using unity’s physics engine though ) with the tile, so I don’t have to implement the actual collision calculation method, but use unity’s and check only with the gameobjects that I want it to. Does this make any sense?
Thanks for your answers btw.!
I would be very surprised if Unity isn’t using some sort of quadtree or octree to prune collisions. If everything but the player is static, most likely it’s going to do a couple of quick tree checks to find the colliders that are close enough to the player to possibly collide with and then only do the full computations on those. In short, the stuff that’s far away isn’t likely to get processed, so I wouldn’t worry much about it. If you’re wondering what the speed difference is, just run it with the collisions turned on and then off to see.
Unity uses Box2D so it’s not what Unity does, it’s what Box2D does and there’s plenty of information on Box2D around.
Ignoring the memory overhead of having lots of colliders, finding contacts and resolving them are the only overhead. I’d be surprised if you’ve not already tried this but just go ahead and add 1000 static colliders and look at the CPU overhead whilst running. There should be no overhead at all, only the set-up costs of those colliders and the memory they occupy.
Static colliders don’t move (or you shouldn’t move them) so they don’t produce contacts themselves so there’s nothing to do each update. Dynamic colliders however can move and do collide with other colliders including static ones so it’s only the contacts for those, that need resolving.
When I integrated Box2D into Unity, I also chose to only produce a single static body and attach any static colliders to it (colliders with no Rigidbody2D component). This means that during each physics loop, Box2D doesn’t have to iterate hundreds/thousands of static bodies, only a single one. Therefore, this means that during an update with (say) 1000 static colliders and a single dynamic collider (player), only the player contact(s) are being resolved.
Back when we were doing a terraria experience, we tried box2D with a ridiculous amount of colliders (static) and there was no impact we could measure with thousands. At least not an impact that would have affected our framerate.