Creating a platform game, raycasting vs colliders and performance

I am currently creating a small platform game and it’s going ok but I have some concerns still and want to do this in the best way possible. I wanted to have maximum control over the movement of the character to really get the feeling right so I am moving it manually using it’s transform. I am also simulating gravity with my controller script instead of using rigidbodies. I do not want to use the Unity character controller since the performance is not that good and it feels like overkill. This is a simple super mario kind of 2d platform game.

Now the big question is how I should deal with collisions in the best way. I want to be able to detect when I hit something to it’s left, right, top and bottom. Right now I am doing this with raycasting and I shoot 3 rays in each direction the same distance as half the width/height of my character, so in total 9 rays per character. This is working fine but I have had some rounding problems and sometimes the character has fallen through a platform when falling fast. I am also uncertain if I should cast the rays in the FixedUpdate or Update method. In the Update method it gets thrown more often ofc but if I get dropped frames I guess things could go wrong(?).

Anyway it has worked good but now I added bullets to the game. I shoot a small ray out in front of the bullet and it does hit but sometimes misses.

So now I tried using colliders instead for the bullet and now it never misses, which did surprise me a little and got me thinking if perhaps I should use colliders for my characters also.

What bothers me is that I have to add a dummy rigidbody to my objects to get hit detection between colliders working. Why is this, why shouldn’t it work without? I am afraid this gives me a performance penalty, even though I am checking isKinematic.

What is your tips guys? What’s the performance difference between say sending out 9 rays or using a collider with a kinematic rigidbody on everything? And why would a bullet miss when using a ray and hit when using a collider? I thought that many times a ray would be a better choice for bullets.

How would you solve hit detection for a 2d platforming game (without the character controller), rays, box colliders, other methods? I’ve even been thinking of using rectangle intersection algorithms similar to using hitTest in flash… What I want is the best performance but also good precision, i am asking for a lot here :wink: Would really appreciate any input!

Im not sure about the performance, I use quite a few of both in my current project and am still at 30FPS on a 2nd Gen ipod touch which I think is really good. But about the rigidbody I remember when I started using unity I couldnt figure out why it wasnt working. But for collisions to register one of them need to have a rigidbody

Yes it’s true that both need a rigidbody but I still can’t understand why this is a must. But perhaps a kinematic rigidbody uses very little cpu?

But what is the most common way of creating a platform game, raycasts or colliders? What have you guys out there been using for your games?

i guess kinematic would use less, cuz its not being controlled by gravity. I dont think it would matter that much in terms of performance though. I dont know how much of a speed difference raycasts have vs colliders, but I would use colliders. I think it would be a bit easeir

Hi!
I think you are trying to solve the wrong problem :wink:
In my experience these types of things, (collision detection etc) unless horribly engineered take up very little of the processing power of the machine. The performance bottlenecks will be other stuff in your scene, for sure.

I am very much in favor of having as easy a system as possible; use colliders. That way you can easily see what you have and might even have someone else, who doesn’t fully appreciate the beauty of you homebrew, build levels and create stuff for your game.

kinematic wont collide however ( as far as messages go ).

Use a character controller. You’ll save yourself a huge headache and lots of time using it. Its perfect for platformers.

It in no way is overkill, the character controller component supplies very basic functionality that does exactly what your asking for here.

The reason people say its not very good with performance is because its not as automatic-fast as other components as your in charge of updating it and alot of people will make a level with one player character controller and 50 enemy character controllers and constantly update all 50 of them.

The tricks to success when it comes to character controller and performance are:

  • don’t use alot of them
  • don’t update/move when you do not need to ( like when your idle )
  • avoid updating things when it makes sense to ( like when a enemy is off screen )

With that said its important to realize with a platformer in most cases you won’t need a character controller for every enemy type. The biggest issue that can come up with using character controllers is mainly frame rate and interpolation. I don’t mean frame rate as in it drags it down, but if your not updating the character controller at a fixed time step its easy to have your gravity calculations pull someone down faster at a slower fps. But this problem would be there even if you rolled your own controller. The other problem comes in where the collision events for the character controllers only occur between the call to Move or Simple move, so that means if a projectile were to be fired at your player and he didn’t move into it, you wouldn’t pick up on it from the controller impact messages. Theres ways around it but i can tell you its still a much better way to go than dealing with all the problems and garbage collection that goes on with trying to make your own component to handle this.

If you must do it yourself, use things like CapsuleCast or SphereCast instead of doing like 9 ray traces. I can’t speak if it will perform better to use capsule over 9 rays but it will be a lot more stable. But still the most common way i’ve seen platformers done is with character collider.

@BDev

Thanks for your answer!

Maybe I wasn’t very clear in the beginning when I said things are just going ok. What I have done is that I have fully created the platform character controller already using raycasts (9 of them) and normal translates etc. My character is currently moving and behaving perfectly. The question should perhaps be if I would get even better performance if I used boxcolliders instead. I also had problems with things like raycasts shooting out from bullets that would sometimes miss, which does not happen if a slab on a boxcollider and kinetmatic rigidbody on the same bullet and use OnTriggerEntered instead.

I also did not mention that I need this to run on an iPhone. The thing is I don’t want to use the character controller form Unity since I want the exact same character controller behavior for my enemies, which I now currently have, so there is no point for me in using the character controller from Unity, especially since my code is already working great. Im just discussing if it could become even better if I switched to using boxcolliders instead? CapsuleCast also seems interesting but perhaps I want a more “boxy” hitzone, which there was a boxcast something :slight_smile: I guess I could roll my own rectangle intersecting code also but that would mean looping through all platforms and characters all the time, but perhaps that would still give me better performance since it’s so simple?

My game which runs on a ipod 2g at 45fps and easily at 60fps on my ipod 4g uses character controller for the main character. Unless your going to have like 6 or more enemies on screen and they absolutely need to use character controller i still think character controller is the way to go.

With the question about performance with box colliders, i don’t fully understand how your doing it currently so i couldnt really give you a good answer here.

Capsule or Sphere cast will not change how the colliders shapes are. both of these cast methods just act like a thick raycast. It won’t change anything about a boxy hit zone when you compare it to raycast.

Since were talking about a game mainly played on two axes there should be no need for a box cast since a sphere or capsule cast in 2D is basically the same as what your asking for, as far as i know theres no actual caps on the trace, its more like a cylinder and oblong cylinder cast ( which again in 2D would look like a rectangle ).

One thing i’d like to mention though, its very cool your ready to jump in and program special things in, but one thing i’d like to stress is that most of unity is native and the only time you should think about rolling your own approach is after you’ve checked all available options provided by unity as it will take mono on average 1.5x time to do what is done natively, but the real drawback is if you do anything with arrays or class construction they will spike up GC moreso ( though if you really got strict and used struct for alot of things you can get past this in some cases ).

With that said, rectangle intersection should be simple, but the harder part about is iterating through everything optimally. But if you do go this route i’d much more suggest using Bounds over Rect. Bounds functions are very fast, The square distance to point method on Bounds is very fast and have used it intensely in the past with good performance.

Thank you very much for your feedback BDev you are saying many interesting things here I did not know until now.

Anyway since the last time I have fully implemented my own collision handling using intersection testing. I did a test yersterday with about 50 characters running down on my platforms and had 58-59 fps on my iPhone 3GS so performance is very good so far. I have still stayed away from the character controller since I would need about 50 of them which I am guessing would slow it down too much.

With that said, i’m still not certain this is the best way since I’m not sure if this is easier on the cpu than Unitys built in physics handling.

What I am basically doing now is moving the characters in X and then Y and checking for collisions. By doing it in two steps I can easily find out if I am hitting a left wall, right wall, ceiling or ground. If I hit something I position the character directly on the ground, next to the ceiling and so on. Just as you point out I am looping through every object (that I want to collide against) checking if they intersect. I am currently doing this with a very simple

if (RectA.X1 < RectB.X2 RectA.X2 > RectB.X1
RectA.Y1 < RectB.Y2 RectA.Y2 > RectB.Y1)

algorithm. I dont want to check just a point (say a single point below the center of character) but instead the whole area of the character. I don’t want him to fall down onto the next platform unless the entire body is outside of the platform. Could this be done with Bounds and event faster you say?

What I am going to try next is to see if I get even better performance if I switch my collision handling code and uses Unity’s instead by having BoxColliders (using trigger) and kinematic rigidbodies on my characters. It should allow me to use the same code as I currently have for detecting if I hit ground, up, left etc. I really want to stay away from using non-kinematic rigidbodies since it don’t give me the arcade feel I am looking for when controlling the character. I do not want to apply forces to get him moving correctly. This must mean I have to fix the position of the character myself after getting an OnTriggerEnter callback right? With the current approach I can easily change a few lines of code and use the collision checking atleast from PhysX. Is there btw any other way than using OnTriggerEnter for checking which colliders my character is currently in contact with? So I don’t have to create internal lists myself all the time.

This is a very interesting topic and I will return with more information about how this is going asap! I will hopefully be able to test more tonight! Any further input is greatly appreciated, and big thanks to you BDev.

UPDATE:

I have now tried creating a second solution where I use raycasting to decide if the next position (based on velocity, moving speed etc) would be inside a collider. So far this seems to be working very well! Since I only cast a ray between the current position and the next position I basically get continuous collision detection (with very short ray casting distances) which the old method of intersection checking did not give me. The performance also seems to be better or almost the same, but I like this solution more since it uses the PhysX engine and I don’t have to keep track of all colliders. The old solution would most likely not scale very well when adding more platforms.

This is by far the best solution I have found yet, and that includes testing the character controller, rigidbodies or triggers. The nice thing here is that I have total control over everything and the characters will never be drawn inside a collider since I always use raycasting to check collisions before actually moving the character over there! Performance wise I tried having about 30 characters on screen, all moving at the same time, I currently have 58-59 fps on the iPhone 3GS, I could never manage that with the character controller. I’ve also created a system where the collision detection only activates when moving, jumping etc which saves even more performance especially for the main character.

Out of curiosity how are you controlling character movement? Is it through Translate.Transform? Also how do you handle the collision then when you do get a hit on the raycast? Your solution sounds very efficient and I think I may give it a go in my project.

@InnocentBystander

I am modifying the transform directly yes. What I am basically doing is that in each Update (FixedUpdate would also be ok) I calculate what the next position will become. But before moving the character to that position I use raycasting to detect if there is anything in the way. I do this in the most optimal way by shooting a small number of rays, most of the time one is enough but sometimes up to 6-7 will be fired. If there is anything in the position I do not move the character. You could move the character tough and put him next to the obstacle for the most accurate results.

The nice thing with this is that it gives me total control over the character and I do not have to use things like AddForce or character controllers. I can also have a lot of enemies and still run at 60 fps something I could not do with the character controller.

I think this is the kind of approach used by many simple platform games that do not use Unity, for example when they are built using Flash.

You’re making this way more complicated than it needs to be.