Easier to control 2D characters with rigidbodies

Hey all,

Hoping you can help me with Rigidbody2D’s and getting characters to move well. At the moment, I’m playing around with the peanut character from the 2D example project. He moves with rigidbodies.

			float h = Input.GetAxis("Horizontal");

			// The Speed animator parameter is set to the absolute value of the horizontal input.
			anim.SetFloat("Speed", Mathf.Abs(h));

			// If the player is changing direction (h has a different sign to velocity.x) or hasn't reached maxSpeed yet...
			if(h * rigidbody2D.velocity.x < maxSpeed){
				// ... add a force to the player.
				rigidbody2D.AddForce(Vector2.right * h * moveForce);
			}

This moves him fine, but the forces make him uncontrollable. For example, getting him to stop before he walks off the edge of a cliff requires an understanding of forces and acceleration that I don’t really expect from anyone playing my game. How do I get him to stop when there’s no input? So moves more like Mario or other 2d games, not a go-kart. Increasing things like mass and friction can make him easier to control, but then he’s too slow. If I up the speed, I’m back at square one.

You can always set the velocity to 0, or degrade it over a short amount of time while the key is not pressed.

3 Answers

3

If you’re going to use physics and forces to control the movement of your character, then unfortunately you will have to keep playing around with the force, friction/resistence and mass settings until you get it the way you want it to work. Look into 2D physics materials that you can apply to your character which I think also provides some resistence options.

If you want the character to stop quicker than it takes it to accelerate, you could even do something programmatically about it by, for example, applying a certain amount of force in the opposite direction of movement whenever the player is not holding down a button, but also while the character’s velocity is above zero. This would achieve the effect of it taking a less amount of time to stop when the button is released, compared to the amount of time it takes to accelerate to max speed.

But in brief, if you want to use physics for your character controller, then you will just have to tweak it until you get it just right.

Games like Mario and “other 2D games” like you mention do not usually use any kind of physics modelling, thus all movement in the game is done manually, so to speak, by translating the position of the player character. The acceleration and deceleration visible in these games is also done “manually”, to give the illusion of weight to the character, by gradually increasing the speed of the character movement until it reaches a certain max, and then when the movement button is let go, by gradually decreasing this speed until it reaches a min, such as zero.

Thanks for this, I've marked it correct because it goes a bit more in depth into it than Spinner, but his code snippet is worth a look too for anyone else looking for something similar.

People forget that when we(real world entities) stop, we have to apply forces in the opposite direction of our movement. Here is how you do that:

if(abs(h) < stopThreshold)
{
  applyStopForce();
}

applyStopForce() applies a force opposite and proportional to the movement. You will have to play with the value, but this will have the desired effect.

Thanks Spinner. And thanks for the succinct code, I'll start playing around with this a bit, plus spend more time playing with the friction values.

using rigidbody.velocity will stop a character in his or her tracks as long as the physics materials are regular/undefined.