0
\$\begingroup\$

I am new to Unity, and am trying to make a simple 2D platformer from this video, and I am trying to modify it to prevent the player from being able to switch directions during a jump. Right now, you can jump and then move. I want to freeze the left/right player controls and give control of the players location FULLY to the rigidbody. Can anyone help? I can update with any additional info y'all need.

Here is my player controller script:


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private Rigidbody2D rb;
    public float speed;
    public float jumpForce;
    private float moveInput;

    private bool isGrounded;
    public Transform feetPos;
    public float checkRadius;
    public LayerMask whatIsGround;
    private bool upKeyPressed;
    private bool upKeyHeld;
    private bool upKeyUp;

    private float jumpTimeCounter;
    public float jumpTime;
    private bool isJumping;

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

    void FixedUpdate()
    {
        moveInput = Input.GetAxisRaw("Horizontal");
        rb.velocity = new Vector2(moveInput * speed, rb.velocity.y);
    }

    void Update() {
        isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, whatIsGround);

        upKeyPressed = Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.UpArrow);
        upKeyHeld = Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow);
        upKeyUp = Input.GetKeyUp(KeyCode.W) && Input.GetKeyUp(KeyCode.UpArrow);

        if(moveInput > 0 && isGrounded == true) {
            transform.eulerAngles = new Vector3(0, 0, 0);
        } else if(moveInput < 0 && isGrounded == true) {
            transform.eulerAngles = new Vector3(0, 180, 0);
        }

        if(isGrounded == true && upKeyPressed) {
            isJumping = true;
            jumpTimeCounter = jumpTime;
            rb.velocity = Vector2.up * jumpForce;
        }
        
        if(upKeyHeld && isJumping == true) {

            if(jumpTimeCounter > 0) {
                rb.velocity = Vector2.up * jumpForce;
                jumpTimeCounter -= Time.deltaTime;
            } else {
                isJumping = false;
            }
            
        }

        if(Input.GetKeyUp(KeyCode.UpArrow)) {
            isJumping = false;
        }
    }
}
```
\$\endgroup\$
1
\$\begingroup\$

Did you try checking whether you're grounded before applying the horizontal input to the velocity?

(You should also be applying your jump hold logic at the same time, not in Update, so held jumps are handled consistently regardless of framerate)

void FixedUpdate()
{
    Vector2 newVelocity = rb.velocity;

    isGrounded = Physics2D.OverlapCircle(feetPos.position, checkRadius, whatIsGround);
    if (isGrounded) {
        moveInput = Input.GetAxisRaw("Horizontal");
        newVelocity.x = moveInput * speed;
    }

    if (isJumping) {
        upKeyHeld = Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow);

        if(upKeyHeld) {
            if(jumpTimeCounter > 0) {
                // Don't name a variable "force" if it's measuring "speed".
                newVelocity.y = jumpSpeed;
                jumpTimeCounter -= Time.deltaTime;
            } else {
                isJumping = false;
            }            
        }
    }

    rb.velocity = newVelocity;
}

You'll probably also want to change your jumping lift-off code so that it doesn't reset the horizontal velocity to zero:

if(isGrounded == true && upKeyPressed) {
    isJumping = true;
    jumpTimeCounter = jumpTime;
    rb.velocity = new Vector2(rb.velocity.x, jumpSpeed);
}
\$\endgroup\$
4
  • \$\begingroup\$ Thanks for your input. I am new to Unity, so I was just following Blackthornprod's video. Am I correct in thinking that returning the values for upKeyHeld, upKeyPressed, and upKeyUp should all be returned in the Update() method, while the actual responding should happen in FixedUpdate()? \$\endgroup\$
    – RMCodes
    Sep 11 at 0:23
  • \$\begingroup\$ Not for held actions — Unity will cache those for you just fine. Up/down actions should be handled in Update to ensure they're handled exactly once in the frame (a frame of input might get zero, one, or more FixedUpdate calls). And you shouldn't use GetKey... — use GetButton... or the new Input System package instead for remappable controls. Either of these alternatives will automatically combine keys/buttons you've defined to map to the same action, so you don't need to or-together multiple keys in your code. \$\endgroup\$
    – DMGregory
    Sep 11 at 0:32
  • \$\begingroup\$ Oh, cool. I will read up on those. Thanks for your time! \$\endgroup\$
    – RMCodes
    Sep 11 at 15:04
  • \$\begingroup\$ Hi. I just got back to Unity, and after testing, I was unable to jump. I probably messed up with where everything goes and what I am supposed to delete. Would you please edit the answer to have the entire file (through pastebin or something similar)? It would mean so much to me. \$\endgroup\$
    – RMCodes
    Sep 23 at 18:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.