Unity 3D Aerial movement and jumping problem

Viewed 47

Aerial Movement Problem

I've followed a few tutorials and I've set up a decent base for a game, - basic player movement, entity animation, health, HUD UI, etc. - but I wanted to make the movement a bit smoother, less snappy, more physics-based, you get the gist. I made it a bit better and it definitely meets all the requirements for terrain-based movement (i.e: movement across physical surfaces - while the player is on the ground), but I want jumping to be a bit more dynamic, and I know what I want to do but I'm having trouble doing it.


Here's the issue:

If the player moves (regardless of whether sprintActive is toggled or not) and they jump after moving, the player gains speed in the air way too fast, and they can't move in any direction other than forward (relative to their rotation).

Here's the objective:

I set it up so the velocity is simply redirected to whatever direction is forward from the playerRB, but I think I would prefer if the velocity didn't immediately change direction, but rather gradually curve as the player tries to move a certain direction? I know I may be asking for a lot, but some advice on how to do this, or if I should try a different approach, would be very much appreciated.


Code used:

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

public class RFPSPlayerMovement : MonoBehaviour
{
    public float speedForce;
    public float jumpForce;
    public float diveForce;
    public Transform groundCheck;
    public float groundDistance = 0.25f;
    public LayerMask groundMask;
    
    private Transform playerBody;
    private Rigidbody playerRB;
    private bool isGrounded;
    private bool sprintActive = false;
    private bool delay = false;
    private float lateralSpeed;
    private Vector3 velocity;
    
    float xMov, zMov;
    float xSpeed, zSpeed;
    
    IEnumerator DelayTimer(float duration)
    {
        delay = true;
        yield return new WaitForSeconds(duration);
        delay = false;
    }
    
    void Start()
    {
        playerBody = GetComponent<Transform>();
        playerRB = GetComponent<Rigidbody>();
    }

    void Update()
    {
        xMov = Input.GetAxisRaw("Horizontal") * Time.deltaTime;
        zMov = Input.GetAxisRaw("Vertical") * Time.deltaTime;

        if(Input.GetKey(KeyCode.LeftShift))
        {
            sprintActive = true;
        }
        else
        {
            sprintActive = false;
        }
        
        if(Input.GetKey(KeyCode.W))
        {
            Movement(0, speedForce);
        }

        if(Input.GetKey(KeyCode.S))
        {
            Movement(0, -speedForce);
        }

        if(Input.GetKey(KeyCode.A))
        {
            Movement(-speedForce, 0);
        }

        if(Input.GetKey(KeyCode.D))
        {
            Movement(speedForce, 0);
        }

        if(Input.GetKey(KeyCode.Space))
        {
            if(delay == false)
            {
                if(isGrounded)
                {
                    StartCoroutine(DelayTimer(0.05f));
                    Jump(jumpForce);
                }
            }
        }
    }

    void FixedUpdate()
    {
        velocity = playerRB.velocity;

        lateralSpeed = new Vector2(playerRB.velocity.x, playerRB.velocity.z).magnitude;
        
        isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask);

        if(isGrounded)
        {
            velocity = new Vector3(
                xMov + (float) (playerRB.velocity.x * 0.90), 
                playerRB.velocity.y,
                zMov + (float) (playerRB.velocity.z * 0.90)
            );
        }
        else
        {
            velocity.x = (float) (playerBody.forward.x * lateralSpeed);
            velocity.y = playerRB.velocity.y;
            velocity.z = (float) (playerBody.forward.z * lateralSpeed);
        }

        playerBody.eulerAngles = new Vector3(0, playerBody.eulerAngles.y, 0);

        playerRB.velocity = velocity;
    }

    void Movement(float xAmount, float zAmount)
    {
        if(sprintActive)
        {
            xSpeed = (float) (xAmount * 2);
            zSpeed = (float) (zAmount * 2);
        }
        else
        {
            xSpeed = xAmount;
            zSpeed = zAmount;
        }

        playerRB.AddRelativeForce(new Vector3(xSpeed, 0, zSpeed), ForceMode.Impulse);
    }
 
    void Jump(float yAmount)
    {
        playerRB.AddRelativeForce(new Vector3(0, yAmount, 0), ForceMode.Impulse);
    }
}
0 Answers
Related