Now that The Wisp is over with, I’d like to talk about on of the problems I faced in development, the problem of using too many colliders.
The game uses a 2D lighting system bought off the asset store which draws a mesh that represents a light shining amongst geometry. The system used Physics2D.Raycast a lot which checks against all colliders in the scene to find which ones it hit.
This performance bug was not an easily fixable problem, it wasn’t my code, so I needed to optimise the other end of this problem, the number of colliders checked against. After some thought, I came to the conclusion that I would need to convert all existing colliders into a single large collider that the physics engine would check against once per raycast call.
I realised that the colliders of the scene are axis-aligned, which means I could paint the current colliders to a grid and make a single collider out of that.
I made a 2 dimensional grid of booleans where true meant a collider was overlapping this grid point. This was easy, just painting the colliders to the grid, by finding the grid location of the bottom left of the collider and how large it is horizontally and vertically, I was able to iterate through that, turning all that I go over to true. If I draw cubes using the Gizmos class in Unity I get:
With this I could now figure out the collider. The way I did this was I drew a line around the true values in the grid of booleans.
To achieve this, I made another 2D array, but with an additional column and row. The idea behind this array is to find the direction a point needs to be going clockwise around the trues in the grid. At each point in the new array, I would check all directions starting with right and going clockwise. The way I would check if it is that direction would be to check if the grid point forward and to the right relative to the current direction was true and if the grid point forward and to the left relative to the current direction was false. If both were true, then that means the current direction is the direction I’m up to. If no direction is found, I would just but a null value, in this case since I’m using an int to represent the direction (0 = right, 1 = down, 2 = left, 3 = up) I would have it as -1.
The result looks like this:
The next thing I did was iterate through all of the new array to find the first direction, when found I would start a method that would get that loop.
The loop was just a while loop that would repeat if the current position in the grid was not the same as the original position in the grid. When I had a grid point, I would get the direction, add the current position to an array of grid points if the new direction is not the same as the current direction, move the current position to the grid point I was just at plus the direction it had, then set the old grid’s value to -1. I would do this until I found a -1 which means I would finish the loop, store it, and erase it at the same time. I would then continue to iterate through the world until either I found another direction and do what I just said, again, or reach the final position of the grid which would kick me out anyway.
Once I had all my points, I would throw it at the Polygon Collider which would easily build the collider for me:
And there we have it, my collider with essentially a step by step guide, though with none of the maths which is vital in doing this.
- The lighting system we were using, I found out didn’t support Polygon Colliders
- The new lighting system I am currently using has this support, but doesn’t have some features.
- I had a loop counter in a method which I hoped would stop infinite while loops., but instead broke the system.