rigidbody2D : X velocity is slowed down when I jump.

Hi everybody! First question here. :slight_smile:

From the code I made for a 2D game or even in the Unity 2D demo project, when I jump the velocity.x is maxed at 2 and if I release the arrow key in middle air, the character seems to speed up. Don’t know what cause that. At first I tough the problem was on my side but when I tested again the Unity 2D demo project, I noticed the same problem. You’ll especially notice it when you release the move key middle air. Cans someone explain this to me or have fixed it yet? Thanks!

Here is my code :
using UnityEngine;
using System.Collections;

public class PlayerControlBonhomme : MonoBehaviour {

	public float moveForce = 365f;
	public float maxSpeed = 5f;
	public LayerMask groundLayerMask;
	public float jumpForce = 1000f;

	private bool faceRight = true;
	private Animator anim;
	private Transform groundCheck;
	private bool jump;
	private bool grounded = false;

	// Use this for initialization
	void Start () {
		anim = GetComponent<Animator>();
		groundCheck = transform.Find("groundCheck");
	}

	void FixedUpdate () {
		float h = Input.GetAxis("Horizontal");

		anim.SetFloat("speed", Mathf.Abs(h));

		if(h * rigidbody2D.velocity.x < maxSpeed)
			rigidbody2D.AddForce(Vector2.right * h * moveForce);

		// Si la velocité est trop grande, on se créé un nouveau vector2 qui la limite
		if(Mathf.Abs(rigidbody2D.velocity.x) > maxSpeed)
			rigidbody2D.velocity = new Vector2(Mathf.Sign(rigidbody2D.velocity.x) * maxSpeed, rigidbody2D.velocity.y);

		if (h < -0.01f && faceRight) {
			Vector3 scale = transform.localScale;
			scale.x *= -transform.localScale.x;
			transform.localScale = scale;
			faceRight = !faceRight;
		}

		if (h > 0.01f && !faceRight) {
			Vector3 scale = transform.localScale;
			scale.x = Mathf.Abs (transform.localScale.x);
			transform.localScale = scale;
			faceRight = !faceRight;
		}

		if(jump)
		{
			rigidbody2D.AddForce(new Vector2(0, jumpForce));
			jump = false;
		}

	}

	// Update is called once per frame
	void Update () {
		grounded = Physics2D.Linecast(transform.position, groundCheck.position, groundLayerMask);  
		
		if(Input.GetButtonDown("Jump") && grounded)
			jump = true;

		print (rigidbody2D.velocity.x);
	}
}

I have this exact same problem. In my own game, as well as thee Tower Bridge Defence example. I would upvote the question, but I can't, since I don't have 15 reputation.

–

1 Answer

1

Damn… answer length is limited.. my answer got cut - I try to distribute on comments…

Oh, the code is not that nice… that’s from an official Tutorial?
I see multiple problems… and also where the speedup comes from.

Ok, lets try to fix that. I won’t check any code in unity, so I might have syntax errors, but you should be able to fix them if you understand the code above.

Here’s the first Problem:

if(h * rigidbody2D.velocity.x < maxSpeed)
   rigidbody2D.AddForce(Vector2.right * h * moveForce);

This is problematic in multiple ways…
First you think that this just checks for movement to the right, because it only checks for vel.x not being too big, but what happens if we’re moving to the left? Well then h is also negative and a negative vel.x multiplied with a negative h makes it positive again, so you can check against maxSpeed… well so you thought.
Because actually, we can still slide/move to the left and then press right to get a positive h, which makes the whole thing negative… which passes the check and doesn’t lead to a wrong movement, but the designer clearly didn’t think about that case.

Oh wait, you removed deltaTime and your opening brackets don't match the closing ones. I take back that you put it where it belongs :D Anyway.. it's fixed in my code, so you can get it there...

–

Your code still doesn't decelerate when the key is released, though. I have to multiply by h after adding the acceleration to the velocity. E.g. horizVel = Mathf.Clamp( (horizVel + (moveForce/rigidbody2D.mass)) * h *Time.deltaTime, -maxSpeed, maxSpeed); EDIT: This approach also seems to ignore friction. :(

–

Oh yes, that's true. let's add that. Now... in rigidBody2D this is called linearDrag and if they implement it right, it's a function of the velocity and body form, but we don't need to go that complex, we just add some dampening: public float: moveDampening = 0.9f; // play with the value till it feels right ... horizVel = Mathf.Clamp(moveDampening * horizVel + (moveForce/rigidbody2D.mass)hTime.deltaTime, -maxSpeed, maxSpeed);

–

Just to make sure you know how to use moveDampening ... if you set it to 1, there will be no dampening and 0 means it dampens so hard that you probably won't even be able to build up the full speed... depending on your moveForce. 0.9 means you lose 10% of speed every frame (fixedupdate "frame" that is)

–

Can you accept the answer?

–