The Character-Ripple interaction is an integral part of the core gameplay. It is the driving force with how the characters interact with each other in the game. Strategically moving to the right position to set up an attack while dodging an opponent’s push on the downbeat of the song. If the collision detection between the characters and the ripples is broken, or nonexistent, then the base gameplay is not there, which is a problem.
What we want out of our collision detection is the ability to handle different shaped ripples that the characters can generate. So for example, we want character to generate circles and another character generate diamonds, as seen in the gif. I spent the last week revamping our collision detection to incorporate Vectrosity and the ability to handle different shapes.
Click image to watch the gif
Vectrosity is the unity plugin we have transitioned to using. It makes drawing vectors in Unity a snap, which is helpful for us since we don’t have a designated artist, and or ripples are very minimalistic. But back to collision.
Up until this point, we have been using the collision system that was implemented in the original pitch prototype. It was very simple detection based on the radius of the ripple, the position of the character and the width of ripple. Pretty much it just check if the distance from the characters position to the center of the ripple was roughly the length of the radius, give or take some width. It got the job done, but only if we kept the circle ripples.
Then came along our “first encounter.” It’s a battle with a boss character set to it’s own music track. The boss has a special ability, this time a size adjustable ripple. So to the beat of the music, the boss can change the radius of the ripple from increasing to decreasing or vis versa. It was a fun battle, it was hard, but people enjoyed it. But during testing we noticed something, either the players got really good, or something broke with the collision. After playing for a bit, if you survived long enough in the fight, it all of sudden became really hard to die. Something went wrong with the collision. So what better time than now to change up the system?
The first step was to do away with our current collision and see what Vectrosity had to help us. After looking at some documentation and fiddling around with it, we found what we were looking for:
VectorLine.collider = true;
This turned on Unity colliders for the lines that were representing the ripples. After a little more fiddling, we figured out how access the collider directly and make it a trigger. We slapped on a 2D circle collider for the players, added an OnTriggerEnter2D and BAM, it worked! We set up a test environment and tried out some different shapes, like rectangles and hexagons, the collision detection worked flawlessly. Or so it seemed. We then hooked it up to the boss encounter and… frame rate issues. Our frame rate at dropped from over 60fps to 40fps once the ripples started spawning. As the song picked up and more ripples were being generated, the frame rate dropped even more, but the ripples were still being spawned based on time. So they were being created faster than they we disappearing. This created a positive feedback loop until it dropped to 3fps.
What went wrong? It took us a day or two to figure out. At first we thought it may have been an issue with our object pooling, but tweaking that didn’t seem to help out the frame rate. I took a look at how we were creating our circles. We were calling Vectrosity’s makeCircle function. Which there is no harm in that, but it is a pretty intensive call and we were calling it every frame, so that was a problem. Every time make circle was called it would delete the old points, make some new ones, then make new colliders for new points. So garbage collection was kicking in. We ended up making it so that makeCircle is only called once at the beginning when the ripple is spawned, and then on the update we loop through the points and expand the radius as needed.
This helped a little bit, but it still didn’t solve the issue. After a little more testing and tweaking variables, we found the source of the problem. It was the edge colliders, or more so how Vectrosity handled the colliders. When you make a VectorLine, you pass in a list of points for the line to use. We originally had it at 128 points to make the circle, and lowering it to 32 improved frame rate, but it looked much less like a circle. When you turn on colliders for the VectorLines, it uses the list of points you pass in to generate the edge colliders. But the standard edge collider used twice the points that were passed in because it stores points twice. But it doesn’t end there, the lines in Vectrosity have a width, so there is and edge collider on the outside of the line AND one on the inside. So it needs another list of points for that. So it ended up using about 4 times as many points that were passed in to create it. So with our original point set we passed in, 128 points becomes and additional 512 points. And since there are multiple ripples on the screen at a time, it quickly adds up.
Setting the ripples to have 32 points brought the game back to a playable state, and it worked using different shapes too. So we were able to test out the game with that and get some feedback with better collision. One of them being that the game was perceived as much harder now, since the collisions actually worked for the entire boss fight. But there was still the frame rate issue we had and if we made the ripples more of a circle, and every now then, players would die in the center of the ripple. So the collision wasn’t perfect, but it worked for the time being.
Next post I will go into more detail on the final stage of collision checking where we did away with unity collisions and used Circle-Line collision to solve our issues.