How do I make my 2D character jump?

I’m creating a 2D platformer and I’ve been trying to make my character, a duck (bird?), jump. Here’s the code. It’s not the most beautiful code, I know.

using UnityEngine;
using System.Collections;

public class PlayerMovement : MonoBehaviour {
    public GameObject character;
    public float jumpSpeed;
    public Rigidbody2D rb;

    void OnCollisionEnter2D()
    {
        character.transform.tag = "onFloor";
    }

    void OnCollisionExit2D()
    {
        character.transform.tag = "Jumping";
    }

    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    void Update() {
        if (Input.GetKey(KeyCode.RightArrow))
        {
            character.transform.Translate(new Vector3(3.25f, 0, 0) * Time.deltaTime);
        }
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            character.transform.Translate(new Vector3(-3.25f, 0, 0) * Time.deltaTime);
        }
        if (Input.GetKey(KeyCode.D))
        {
            character.transform.Translate(new Vector3(-3.25f, 0, 0) * Time.deltaTime);
        }
        if (Input.GetKey(KeyCode.A))
        {
            character.transform.Translate(new Vector3(-3.25f, 0, 0));
        }
    }

}

}

It looks like you’ve got physics handling the ground check, and you’ve got a reference to a rigidbody, so why not use physics to handle all the movement?

Would something like this work for you?

public class PlayerMovement : MonoBehaviour
{
    public GameObject character;
    public float moveSpeed = 3.25f;
    public float jumpSpeed;
    public Rigidbody2D rb;

    private Vector2 playerInput;
    private bool shouldJump;
    private bool canJump;


    private void Start()
    {
        rb = character.GetComponent<Rigidbody2D>();
    }

    // get input values each frame
    private void Update()
    {
        // using "GetAxis" allows for many different control schemes to work here
        // go to Edit -> Project Settings -> Input to see and change them
        playerInput = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));

        if(canJump && Input.GetKeyDown("Jump"))
        {
            canJump = false;
            shouldJump = true;
        }
    }

    // apply physics movement based on input values
    private void FixedUpdate()
    {
        // move
        if(playerInput != Vector2.zero) {
            rb.AddForce(playerInput * moveSpeed * Time.fixedDeltaTime, ForceMode2D.Impulse);
        }
      
        // jump
        if(shouldJump) {
            rb.AddForce(Vector2.up * jumpSpeed, ForceMode2D.Impulse);
            shouldJump = false;
        }
    }

    private void OnCollisionEnter2D(Collision2D col)
    {
        // allow jumping again
        canJump = true;
        character.transform.tag = "onFloor";
    }

    private void OnCollisionExit2D(Collision2D col)
    {
        character.transform.tag = "Jumping";
    }
}
1 Like

Not to be a nuisance, but this: [quote=“LiterallyJeff, post:2, topic: 650823, username:LiterallyJeff”]

  • if(canJump && Input.GetKeyDown(“Jump”))

  • {

  • canJump = false;

  • shouldJump = true;

  • }

[/quote]
triggers an error. I’m not sure if I’m missing something obvious. In my other games, I used transform.Translate so using physics is new to me.

It doesn’t matter. I changed Input.GetKeyDown("Jump") to Input.GetKeyDown(KeyCode.Space). I think you should of used GetButtonDown if you were going to put Jump (not sure about that).

2 Likes

Ah yes you’re right. What i wrote will compile because its a string, but “Jump” is not a valid key, it is indeed a button name. I didn’t actually test the code, my bad.

Using physics is a great way to get your character moving and interacting with colliders. Jumping without physics is a bit more complicated, as you can’t just call “addforce”, you have to move positions every frame for a duration.

The downside to physics is that you lack a bit of control, and the results are not always predictable.

You could program your own physics (easier than it sounds for simple movement and jumping), and use rigidbody.MovePosition for a more controlled physical movement if you prefer.

1 Like

Yes, I see what you mean by “the results are not always predictable”. That’s why I use transform.Translate instead of rigidbody.AddForce. I don’t like the ice-like properties of using physics.

Indeed. One solution to that sliding is to set linear drag very high, and use very high forces to overcome that drag. That will result in stop-on-a-dime movement, but is a bit hacky and makes gravity and jumping a pain, as you will need to change drag based on if the character is grounded, etc. etc. It’s something I’ve done before and it worked, but it was not the most intuitive or clean solution.