Hi friends. I've been busy rewriting the physics component in Glace. The system I had before worked alright, but it was getting a little complicated as I added more features to the game. Basically I need something that uses less tricks and special states.
Glace doesn't use Unity's built-in physics engine. From what I've gathered, it's common for Unity platformers to forego the built-in engine in favor of a raycast-based solution. The reasoning here is even though the built-in physics engine is great, it's really difficult to make it behave as intended for a 2D platformer game. It just wasn't meant to do it.
So back to raycasting. That's how Glace handles physics. Before an object is moved in the world, its shape is cast out in the direction of travel. If the cast doesn't hit anything, the object moves to its destination. If the raycast hits something, well, it's complicated. At least for me.
My old system was cobbled together from various sources on the net, including the super cool Corgi Engine I grabbed from the Asset Store. The Corgi Engine is a great asset that I'd recommend to anyone who’s trying to get a handle on platformers for Unity. It uses a collision detection method a little similar to what I did in the original Glace. That is, when you move an object, you do it one dimension at a time. First on the x-axis, then on the y, with each dimension having its own ray cast. So for a vector (2, 3), you'd first raycast and move 2 along the x-axis, then raycast and move 3 along the y-axis. If youd been at the origin prior, now you'd be at (2, 3). That is, assuming you didn't hit something with those raycasts.
So why perform two separate raycasts instead of just a single cast along the movement vector? One reason: it can give you an idea of what to do with a collision. If you hit something on the x phase of the movement, you know you hit something moving horizontally. You don't have to do any other calculations to know this. Same goes for the y check. Folks will use this to determine whether or not an object is "grounded" (standing on a horizontal surface). If you’re moving an object down during the y phase and you collide with something, you know you hit the ground. If you hit something while moving up you know your character just bumped his head on the ceiling. You get all this without doing any complicated stuff. In the original Glace where I only did overlap tests (no raycasts), it was the ONLY way I knew how to tell if Glace should bounce left/right off a wall or up/down off the ground.
A drawback to the "x then y" method is that it doesn't handle non-right angle surfaces well. If you want slopes in your game, there are some extra tricks you need to manage. This is where things start getting weird and where, in my opinion, the method just breaks down. The Corgi Engine has a pretty nice way of handling these extra tricks, but for me its just too much state to worry about when combined with other things I’m doing. I want to find a different way.
I don't even know if I want slopes in the new Glace. Would it be cool? I mean yea. But would slopes actually make the game more fun to play? I guess I don't know. One thing's for sure though, it'd be nice to try it out.
Anyway, this is what I've been doing! I have a system that I'm pretty happy with. It casts the x and y as a single vector and uses the normals of hit surfaces to determine how to position the object post collision(s). I'll post details on it next!