Day 108 — Player Movement for a 2D Platformer

Connor Fullarton
5 min readJul 1, 2021

Hey and welcome!

It’s that time again where we look into a new way to incorporate movement for our Player object in a game. You’ll see some similarities to the other ways we’ve done this before but the main difference this time is that we’re directly influencing the Rigidbody2D component on our player.

Speaking of, start things off by adding a Rigidbody 2D component to your Player object and then create a new script called Player.

private Rigidbody2D _rigidbody;
private float _movementSpeed = 4.0f;
void Start()
{
_rigidbody = GetComponent<Rigidbody2D>();
}
void Update()
{
float move = Input.GetAxisRaw("Horizontal");
_rigidbody.velocity = new Vector2(move * _movementSpeed, _rigidbody.velocity.y);
}

This bit of code here will get your player moving left and right, you’ll recognise that we’re using Input.GetAxisRaw to get our horizontal inputs instead of the usual Input.GetAxis. This new method returns a whole value of -1, 0 or 1 from the User’s key presses instead of returning an in between value like 0.1. This removes the gradual acceleration and deceleration from the player’s movement which allows it to be more responsive.

Uniquely this time we’re actually directly using the rigidbody instead of just having it on an object for the sake of collisions. Thanks to that we can directly change the velocity in the rigidbody. Also since this is a 2D space we’ll need to make use of Vector2 instead of Vector3 since there’s no Z axis!

Since we’re making use of rigidbody we also don’t need to worry about adding in our own gravity as you can see above. Also if you find yourself falling over instead of moving you’ll need to freeze your z rotation for you Rigidbody 2D component in the Constraints section!

Floor Collision

If you’re not using the same game template as I am you’ll need to make sure that your floor has collision. Since you’re using Tilemap you can add a Tilemap Collider 2D component to your floor and then a Rigidbody 2D component for good measure and you should get something like this:

This will let your player collide with the floor but you may notice here that there are quite a few tiles that will never get collided with which makes them unneeded. You can fix this by adding an extra Composite Collider 2D object to get rid of those.

While you’re here in the inspector for your floor go ahead and create a new layer from the dropdown option in the top right and call it Ground. Set your floor as this new layer and take a note of which number is associated to this layer when you created it, for me it’s User Layer 8.

Player Jumping

Now it’s time to add jumping, in your Player script add in this new code:

private float _jumpSpeed = 5.0f;
private bool _resetJump = false;
void Movement()
{
float move = Input.GetAxisRaw("Horizontal");
_rigidbody.velocity = new Vector2(move * _movementSpeed, _rigidbody.velocity.y);
if (Input.GetKeyDown(KeyCode.Space) && IsGrounded() == true)
{
_rigidbody.velocity = new Vector2(_rigidbody.velocity.x, _jumpSpeed);
}
}
bool IsGrounded()
{
RaycastHit2D hitInfo = Physics2D.Raycast(transform.position, Vector3.down, 0.6f, 1 << 8);
if (hitInfo.collider != null)
{
if (_resetJump == false)
{
return true;
}
}
return false;
}

IEnumerator ResetJumpRoutine()
{
_resetJump = true;
yield return new WaitForSeconds(0.1f);
_resetJump = false;
}

The actual code for the jumping part when we press the space key you should be good and familiar with by now, what’s interesting and unique here is how we’re handling the logic to let our code know whether or not the player is currently grounded.

In the previous project we had the player controller to handle this but now it’s something we need to add manually, normally we would create a separate bool variable but this time we’re making use of something pretty cool which is a return type function.

These are done like normal functions but instead of starting it with void you start with the data type that you want the function to return, in our case here it’s a bool so it’s typed as bool IsGrounded() which when called in our if statement earlier will return either true or false.

The actual logic we use to tell if the player is touching the ground or not is pretty interesting as well as we’re making use of a raycast to create a ray that’s sticking out just below our player and when that collides with the floor we can tell that the player is grounded.

Something you may not recognise is this part 1 << 8, this is known as bit shifting and is surprisingly complex and would probably need it’s own article when I know more about it but this is a pretty old and core programming principle for C# from what I’ve been able to gather and its use in Unity appears to be pretty niche. I do recommend looking into it if you’re interested but for our purposes here were using it to flag our Ground layer we made earlier from 0 to 1.

This means that our raycast is only going to pay attention to our floor and stops it from continually hitting with the player. The 8 here is because our Ground layer is the 8th user created layer so this number will vary depending where yours is.

With that all done though you should have some pretty successful jumping and movement done for you Player!

--

--

Connor Fullarton

Hey and welcome! My name is Connor and my goal here is to put out a daily post for a full year about my game development journey.