Kilyan Fossey
Kilyan Fossey

Reputation: 23

Unity3D Rigidbody player jump is limited while running

I'm trying to programming movements of a main FPS character with a Rigidbody.

Camera and ZQSD displacements works well but jumping while moving is being very restricted :

It's very frustrating, especially for a platform game. Personnaly, I'd like to get same result for both actions.

Here's my C# code :

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

public class FPSMovement : MonoBehaviour {

    public float walkAcceleration = 150f;
    public float maxWalkSpeed = 10f;
    public float jumpVelocity = 500f;
    public float maxSlope = 45f;

    private Rigidbody rb;
    private Vector2 horizontalMovement;
    private bool isGrounded = false;
    private bool doubleJumped = false;

    // Use this for initialization
    void Start () {
        rb = GetComponent<Rigidbody> ();
    }

    // Update is called once per frame
    void Update () {
        if(rb.velocity.magnitude > maxWalkSpeed){
            rb.velocity = Vector3.ClampMagnitude(rb.velocity, maxWalkSpeed);
        }

        transform.rotation = Quaternion.Euler (0, GetComponentInChildren<FPSCamera>().currentYRotation, 0);

        // Entrées clavier ZQSD déplaçant le joueur
        float x = 0, y = 0, z = 0;
        if (Input.GetKey (KeyCode.Z)) {
            x += 1f;
        }
        if (Input.GetKey (KeyCode.S)) {
            x -= 1f;
        }
        if (Input.GetKey (KeyCode.Q)) {
            z -= 1f;
        }
        if (Input.GetKey (KeyCode.D)) {
            z += 1f;
        }
        // Arrêt prompt du glissement
        if ((!Input.GetKey (KeyCode.Z) && !Input.GetKey (KeyCode.S) && !Input.GetKey (KeyCode.Q) && !Input.GetKey (KeyCode.D))
        && isGrounded) {
            rb.velocity /= 1.1f;
        }
        // Saut du joueur
        if (Input.GetKey (KeyCode.Space) && isGrounded) {
            rb.AddForce (0, jumpVelocity, 0);
        // Deuxième saut
        }
        if (Input.GetKey (KeyCode.Space) && !doubleJumped) {
            rb.AddForce (0, jumpVelocity, 0);
            doubleJumped = true;
        }

        rb.AddRelativeForce (z * walkAcceleration, 0, x * walkAcceleration);
    }

    void OnCollisionStay(Collision other) {
        foreach (ContactPoint contact in other.contacts) {
            if (Vector3.Angle (contact.normal, Vector3.up) < maxSlope) {
                isGrounded = true;
                doubleJumped = false;
            }
        }
    }

    void OnCollisionExit() {
        isGrounded = false;
    }


}

I also have impression that player hovers when moving in the airs, but this is not the main question and above all just an impression.

A simple issue with few words to explain, but a real problem to resolve for this type of gaming !

May I ask you, Stackoverflow people to gently help me, a thousand thanks by advance mates.

PS: My native language is the french, so please, don't lose too much time on grammar or other english subtlety :)

Upvotes: 2

Views: 795

Answers (1)

Tubeliar
Tubeliar

Reputation: 856

It is because you clamp the total velocity of the player where you should only clamp the horizontal speed. If you walk at maximum speed and jump, your jump speed is added to the total velocity and your character should actually be travelling at a higher speed than the maximum walking speed. To fix it, you do this:

// Isolate the horizontal component
Vector3 horizontalVelocity = rb.velocity;
horizontalVelocity.y = 0;

if (horizontalVelocity.magnitude > maxWalkSpeed) {
    // Clamp the horizontal component
    Vector3 newVelocity = Vector3.ClampMagnitude(horizontalVelocity, maxWalkSpeed);
    // Keep the original vertical velocity (jump speed)
    newVelocity.y = rb.velocity.y;
    rb.velocity = newVelocity;
}

Upvotes: 1

Related Questions