I’ve seen plenty of opposing recommendations for how to move the player, but I’d like to hear which way is recommended by people with experience (preferably someone with several years of experience or at least one non-hobbyist published game that uses said method).
Specifically, dealing with movement and jumping. I’ve seen several recommended ways of doing so:
-
Don’t use Unity’s physics at all and instead position the player using position.transform.Translate() (or by setting the transform value directly). Then, several raycasts are used to ensure the player doesn’t move excessively in any particular direction. Now, I know that this is a bad idea because it means lots and lots of raycasts in Update(), while I’ve read that it is recommended not to use ANY raycasts in Update or FixedUpdate() due to performance issues.
-
Set the rigidbody’s velocity directly, so every update the horizontal velocities (X and Z) is cleared and then re-set depending on what directional key the player is holding. Jumping is also performed by setting the vertical velocity just once to perform the jump. This set-up works fairly well, but it creates problems when you’re moving against a wall while jumping or falling; namely, your character will “stick” to the wall until you release the movement key.
-
I’ve read several recommendations to resolve this issue by applying a Physics Material with friction set to 0 on all colliders, but this becomes a problem whenever two physics objects interact, such as one character bumping another character. Without friction, a bump can send a player sliding around the ground like it’s made of ice. Since this solution requires friction to basically not exist in the game, it strikes me as a sloppy band-aid solution that doesn’t resolve the real source of the problem.
-
Move by calling rigidbody.AddForce() for movement and for jumping. This seems to be the best solution, except AddForce() seems to demand arbitrarily large forces to be applied, and it’s unclear why. While something like rigidbody.velocity = Vector3.forward * 10; will scoot the player forward at a decent clip, rigidbody.AddForce(Vector3.forward * 10); results in essentially no visible movement whatsoever.
-
One may say, “just increase the multiplied force value until it looks good ”, but that won’t suffice; I’m using a formula to calculate the proper jump height based on how many units I want the player to reach at the apex of the jump. It works perfectly if I was setting rigidbody.velocity directly, but it doesn’t lift the player off the ground at all if I’m calling rigidbody.AddForce() with the same value.
To put a stop to all this confusion, what’s the real way this should be done? Something that allows for precise, tight controls while also allowing flexibility depending on how I’d like the game to feel. Please provide justification for your answer; explain why your way is better than other ways, don’t just spread a personal bias that has no reason beyond habit.
P.S. I’d rather not use the built-in Character Controller because I want to learn how this works under the hood so I’m not reliant on black box solutions.
Hopefully others who find the contrary results of a Google search for how to approach a player controller will find such answers useful as well.