Switching from Unity's Character Controller to a Rigidbody Based Character Controller
10 May 2018 (1 Comments)
After spending a few days trying to write my own physics engine for the character contoller, I realised that I was trying to write my own physics engine for the character controller.
So I had a think about what I was doing and decided to stop using Unity's built in character controller and write my own Rigidbody Character Controller.
What is a Character Controller
How the player moves, jumps, falls, doesn't walk through walls, climbs up steps, cliumbs up ladders.. that's the character controller.
Unity's built in character controller isn't physical. It's a capsule.
It really only has three features. It won't go through shit. It will step up steps. It will step up slopes.
If you want gravity, or sliding, or jumping, or anything else really, you have to implement it yourself. Which is fine but you have to ask yourself at some point why you're not just using a physics object.
So instead of using that I switched to a proper physics object. We make it a capsule shape, and lock its rotation and it behaves pretty much the same. Except instead of manually moving it, we just manipulate the velocity.
Then hopefully, the end result is that it feels the same except slides down slopes.
Problem 1: Sticking
The first problem I came up against was that you could jump and run into a wall, and you'd just stay there pressed up against the wall until you release the movement key.
The solution is to make the collider frictionless, that way it'll just slide off everything.
Problem 2: Friction
So now you made a new problem. There's no friction so it slides around when you're running.
The solution is to apply some friction manually. You can retain icy patches by getting the ground collider and reading the friction value from its material.
Problem 3: Interpolation
Unity's physics interpolation is a minefield. I had interpolation on and it worked great.. until I parented the controller to a moving platform. Then the interpolation was getting fucked up.
So have the character controller as a different object. Don't parent your player to it, but instead lerp your player model into its position. This guarantees that it's going to be smooth, and gives the advantage of abstracting your character controller into a different prefab.
Problem 4: Step Up
I haven't been able to find a good step up solution. In Rust we use a RigidBody based controller and don't have step up. It might not be needed really, it might be wiser to leave it out and make sure everything has nice slopes.
I feel like this would be a lot easier to deal with if the collider is a cube instead of a capsule, since you wouldn't be dealing with the roundness hitting the step. It'd either be on the step or off the step, never half on and sliding off. That might be something I had a fuck about with.
It took me about 4 days from when I decided to actually do it. So I lost a non trivial amount of time, but I feel like I've made something that is a lot more maintable and extendable than I had.
It's made the game engine itself more generic too. Here's an example of that. I have a trigger in the game that pushes the player in a certain direction when they walk into it. For things like conveyor belts or trampolines. You can also drop physics objects onto it and it does the same thing to them. I was able get rid of all the player specific code out of there, because the player is just a physics object.
It also fixed the inertia problems I was having last week.
But the bottom line, I guess, is that I spent a week coding this and still have more work to do to get back to where we were a week ago. I'm about 80% sure it was a good idea, but there's a 20% chance it was a self satisfying masturbation project.
If you want to follow this project you can sign up to the mailing list.
We'll only update you about this project, we won't spam you about other stuff or sell your email address.