I am creating a 2D platformer and right now I have just the basics. I am relying on the built-in physics engine to move my player, but I’ve encountered a problem. Basically, you use the arrow keys to move left and right and Shift to run, and that works fine if you stop running before you stop moving. However if you let go of the arrow key before letting go of shift, the player will rapidly accelerate toward whichever direction you’d been moving in. Why is this happening?
Here’s my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour {
// declare variables
public float walkSpeed, maxRunMultiplier, accelerationSpeed, deccelerationSpeed, jumpPower, wallJumpPower; // speed and stuff of things
...
public float runMultiplier = 1; // for running
bool running;
Transform groundCheck, faceCheck, ceilingCheck;
Animator anim;
Rigidbody2D rig;
Vector2 movementInput;
void Start()
{
...
}
void Update()
{
// get input
GetInput();
...
// assign new velocity
Vector2 newVelocity = Vector2.zero;
Vector2 curVelocity = rig.velocity; // for shorthand
// left and right movement
if (movementInput.x > 0.1f)
{
if (curVelocity.x <= walkSpeed)
{
newVelocity.x = curVelocity.x + accelerationSpeed;
}
else
{
newVelocity.x = walkSpeed;
}
}
else if (movementInput.x < -0.1f)
{
if(curVelocity.x >= -walkSpeed)
{
newVelocity.x = curVelocity.x - accelerationSpeed;
}
else
{
newVelocity.x = -walkSpeed;
}
}
else
{
if(curVelocity.x >= deccelerationSpeed)
{
newVelocity.x = curVelocity.x - deccelerationSpeed;
}
else if (curVelocity.x <= -deccelerationSpeed)
{
newVelocity.x = curVelocity.x + deccelerationSpeed;
}
else
{
newVelocity.x = 0;
}
}
newVelocity.x *= runMultiplier;
...
// get input
void GetInput()
{
// horizontal
if(Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
if(!Input.GetKey(KeyCode.D) && !Input.GetKey(KeyCode.RightArrow))
{
movementInput.x = -1;
}
else
{
movementInput.x = 0;
}
}
else if(Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
if (!Input.GetKey(KeyCode.A) && !Input.GetKey(KeyCode.LeftArrow))
{
movementInput.x = 1;
}
else
{
movementInput.x = 0;
}
}
else
{
movementInput.x = 0;
}
// run test
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
{
runMultiplier = maxRunMultiplier;
}
else
{
runMultiplier = 1;
}
}
}
What’s wrong with it? I’m guessing it has something to do with multiplying by the runVelocity, but I don’t know.
UPDATE 1: I made it only multiply if the movementInput.x wasn’t zero, and that sort of worked, but now if you hold shift, run in one direction, and run in the other as you let go of the first direction it still happens, accelerating you in the direction of the first direction. The code above changed from:
newVelocity.x *= runMultiplier;
To this:
if (movementInput.x < -0.5f || movementInput.x > 0.5f)
{
newVelocity.x *= runMultiplier;
}