New input system problems

I want to make a jump script with responsive jumping, button tapping and holding, coyote time etc. I am trying to implement a way to make the player jump lower when tapping the jump button than when holding it down.
The basic principle i know of is to increase the downward velocity of the player when the jump button is released but the rb.velocity.y > 0f.

My problem is that i am just learning how to use the new input system so i dunno how to do that

Here is my full script…

using System.Net.Http.Headers;
using UnityEditor.Timeline;
using UnityEngine;
using UnityEngine.InputSystem;
using static UnityEditor.Timeline.TimelinePlaybackControls;

public class MovementScript2D : MonoBehaviour
{
    [Header("Jumping")]
    [SerializeField] float jumpHeight;
    
    [Tooltip("The number by which we will multiply gravity when character is falling down to make the jump feel better")]
    [SerializeField] float fallMultiplier;

    [Tooltip("The number by which the gravity is multiplied when NOT holding down the jumpButton")]
    [SerializeField] float lowJumpMultiplier = 2f;


    [Header("Movement")]
    [Tooltip("The maximum speed of the character")]
    [SerializeField] float maxMovementSpeed;

    [Tooltip("Distance from the orign of the gameObject and the raycast being casted for the groundCheck")]
    [SerializeField] float distanceOfRayCast = 2f;

    [SerializeField] float acceleration;


    [Header("Miscallaneous")]
    [SerializeField] LayerMask groundLayer;
    [SerializeField] Color gizmoColor = Color.red;

    Rigidbody2D rb;
    InputSystem inputSystem;
    
    bool onGround;

    // Bool to check the direction in which the player is facing
    bool isFacingRight;

    private void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
        InitializeInputSystem();
    }

    private void Update()
    {
        onGround = Physics2D.Raycast(transform.position, Vector3.down, distanceOfRayCast, groundLayer);
    }

    private void FixedUpdate()
    {
        HandleMovement();
        speedCap();

        if (rb.velocity.y < 0)
        {
            applyFallMultiplier();
        }
    }

    private void InitializeInputSystem()
    {
        inputSystem = new InputSystem();
        inputSystem.Ground.Jump.Enable();
        inputSystem.Ground.Jump.performed += HandleJump;
        inputSystem.Ground.Move.Enable();
        // inputSystem.Ground.Move.performed += Move;
    }

    #region Movement Methods

    private void HandleMovement()
    {
        Vector2 inputMovementVector = inputSystem.Ground.Move.ReadValue<Vector2>();
        
        float targetSpeed = inputMovementVector.x * maxMovementSpeed * Time.fixedDeltaTime;
        float currentSpeed = rb.velocity.x;

        // The player will have this amount of acceleration. Changes with time
        float accelerationFactor = Mathf.Clamp01(acceleration * Time.fixedDeltaTime);
        // Linearly increase from currentSpeed to targetSpeed by the accelerationFactor. accelerartionFactor changes with time
        float finalSpeed = Mathf.Lerp(currentSpeed, targetSpeed, accelerationFactor);

        rb.velocity = new Vector2(finalSpeed, rb.velocity.y);
    }

    void speedCap()
    {
        // Capping the speed from -maxMovementSpeed to maxMovementSpeed. This function returns the present value if it lies in the given range
        float cappedSpeed = Mathf.Clamp(rb.velocity.x, -maxMovementSpeed, maxMovementSpeed);
        rb.velocity = new Vector2(cappedSpeed, rb.velocity.y);
    }

    #endregion

    #region Jump Methods

    private void HandleJump(InputAction.CallbackContext context)
    {
        if (context.performed && onGround)
        {
            rb.AddForce(Vector2.up * jumpHeight, ForceMode2D.Impulse);
        }

        if(rb.velocity.y > 0f && context.canceled)
        {
            rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y);
            rb.AddForce(Vector2.down * Physics2D.gravity.y * (lowJumpMultiplier - 1), ForceMode2D.Force);
        }
    }

    void applyFallMultiplier()
    {
        rb.AddForce(Vector2.up * Physics2D.gravity.y * (fallMultiplier - 1), ForceMode2D.Force);
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = gizmoColor;
        Gizmos.DrawLine(transform.position, transform.position + Vector3.down * distanceOfRayCast);
    }

    #endregion
}

Here is only the jump function…

#endregion

    #region Jump Methods

    private void HandleJump(InputAction.CallbackContext context)
    {
        if (context.performed && onGround)
        {
            rb.AddForce(Vector2.up * jumpHeight, ForceMode2D.Impulse);
        }

        if(rb.velocity.y > 0f && context.canceled)
        {
            rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y);
            rb.AddForce(Vector2.down * Physics2D.gravity.y * (lowJumpMultiplier - 1), ForceMode2D.Force);
        }
    }

    void applyFallMultiplier()
    {
        rb.AddForce(Vector2.up * Physics2D.gravity.y * (fallMultiplier - 1), ForceMode2D.Force);
    }

    private void OnDrawGizmos()
    {
        Gizmos.color = gizmoColor;
        Gizmos.DrawLine(transform.position, transform.position + Vector3.down * distanceOfRayCast);
    }

    #endregion

if(rb.velocity.y > 0f && context.canceled)
        {
            rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y);
            rb.AddForce(Vector2.down * Physics2D.gravity.y * (lowJumpMultiplier - 1), ForceMode2D.Force);
        }

Someone please help. I was able to implement COYOTE time as well but this doesn’t seem to work

I’m not 100% sure about this because I’m not a fan of the new input system, but from what I’m seeing and reading, your code should look like this:

    private void HandleJump(InputAction.CallbackContext context)
    {
        if (context.started && onGround) //Use started, not performed
        {
            rb.AddForce(Vector2.up * jumpHeight, ForceMode2D.Impulse);
        }
        else if (rb.velocity.y > 0f && context.canceled) //else if prevents overriding issues
        {
            rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y);
            rb.AddForce(Vector2.down * Physics2D.gravity.y * (lowJumpMultiplier - 1), ForceMode2D.Force);
        }
    }

There’s no need to increment the downward speed, you can cancel it setting it to 0 and let gravity do the work, it feels a little bit floaty depending on your gravity settings, but most “platformers”, specially the best ones (Mario), feel slightly floaty.

A quick game design tip that you didn’t ask for, but I can’t help but say it.

Coyote time became really popular because it solves, in a technical manner, a design problem which a lot struggle with; level design. You can ignore bad level design with coyote time because it gives the player a bigger chance to jump, but it creates a huge issue; you have to design your levels around coyote time or good players will eventually break your game, you’ll have to consider the distance between platforms with coyote time in mind.

Instead of being a friendly tool to help new players, it dramatically raises the difficulty, hurting your new players. This is why games with amazing level design, like Mario Wonder, don’t use coyote time.

1 Like

Ah I swear I did NOT know that fact about coyote time. But since im a learner, i wanted to learn how to implement some of the thing platformers do to make their games feel more responsive

And btw this should work right?

private void HandleJump(InputAction.CallbackContext context)
    {
        if (context.performed && coyoteTimeCounter > 0f)
        {
            rb.AddForce(Vector2.up * jumpHeight, ForceMode2D.Impulse);
        }

        else if (rb.velocity.y > 0f && context.canceled)
        {
            rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y);
            rb.AddForce(Vector2.down * Physics2D.gravity.y * (lowJumpMultiplier - 1), ForceMode2D.Force);

            coyoteTimeCounter = 0;
        }
    }

I too am not a fan of the new input system but isint it much harder to bind and rebind the controls to a controller or a touchscreen with the old inputSystem?

My goal is to create a character controller and input manager that I can use for all my future projects even if its touch based or controller based

This would be so much easier in the old input system for me cause im already familiar with it but it would be harder to rebind controls and use different inputs right?

Im getting this error when i reload my scene

The new input system allows you to rebind a lot faster, that’s for sure, but it comes with a cost, it’s a little harder to implemented and reflection isn’t particularly optimized, but don’t worry about that, it’s not as if your input will drop your FPS to 10 or something like that.

I’m not 100% sure if that would work, it is a little weird because it says that you can jump when the coyoteTimeCounter is bigger than 0, don’t know how exactly you are increasing or decreasing that variable, but based on assumptions and that the coyoteTimeCounter variable is set to 0 when the button is up, I think you’ll be able to jump all the time because the variable will pretty much always be bigger than 0.

There’s also the issue that if the time counter isn’t bigger than 0 the player won’t be able to jump. Again, not sure how you are modifying that variable.

The errors are telling you that there are missing components in the scene, Maybe you are deleting something when reloading the scene? Or perhaps you forgot to set the parameters in the inspector? If you are using prefabs, be sure to check if the prefab has all its exposed variables in the inspector set correctly.

Coyote time will count DOWN as soon as jump button is pressed. So the input will be registered even if the player is off the ground.

NVM. I think i will stick with the old input system and figure out how to do the different controllers later.

This new input system is WAY too convoluted for a noob like me

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms