FPS Character Controller - Momentum Solution

Hey everyone,

I’m posting this in hopes of helping someone out there struggling with this problem like I was. Character Controller momentum, while maintaining some degree of air control.

I’ve spent so long trying to get this feeling good, scouring Unity answers for solutions but I’ve found next to nothing. I posted a half solution (Not really, wasn’t a nice feeling controller) in 2019 but after playing with it more during quarantine I’ve found something that I feel happy with and I’d like to share with you all.

This is absolutely not the best way to do this, if anyone has criticisms please by all means fire away, I’d love to improve this.

Here’s the Character Controller code, note the initial controller was made with help from Brackey’s FPS controller tutorial -

:

using UnityEngine;


[RequireComponent( typeof( CharacterController ) )]
public class Slug_Controller : MonoBehaviour
{
    /*Private variables*/
    CharacterController _playerController;
    Vector3 _velocity;
    Vector3 input;
    Vector3 move = Vector3.zero;
    float speed;
    bool isGrounded;

    /*Public variables*/
    public Transform groundCheck;
    public float groundDistance = 0.4f;
    public LayerMask groundMask;

    public float walkSpeed = 8f;
    public float runSpeed = 12f;
    public float gravity = -9.81f;
    public float jumpHeight = 3f;
    public float airSpeed = 6f;


    private void Awake() {
        _playerController = GetComponent<CharacterController>();
    }

    void Update()
    {
        isGrounded = Physics.CheckSphere( groundCheck.position, groundDistance, groundMask );
       
        if( isGrounded && _velocity.y < 0f ) { _velocity.y = -2f; }
        input = new Vector3( Input.GetAxisRaw( "Horizontal" ), 0f, Input.GetAxisRaw( "Vertical" ) );
        input = transform.TransformDirection( input );
        input = Vector3.ClampMagnitude( input, 1f );

        ProcessMovement();
       
        HandleJump();

        _playerController.Move( move * Time.deltaTime );

        ApplyGravity();
    }

    void ProcessMovement() {
        if ( isGrounded ) {
            speed = Input.GetKey( KeyCode.LeftShift ) ? runSpeed : walkSpeed;
            if ( input.x != 0 ) {
                move.x += input.x * speed;
            } else {
                move.x = 0;
            }
            if ( input.z != 0 ) {
                move.z += input.z * speed;
            } else {
                move.z = 0;
            }

        } else {
            move.x += input.x * airSpeed;
            move.z += input.z * airSpeed;
        }
        move = Vector3.ClampMagnitude( move, speed );
    }

    void HandleJump() {
        if ( Input.GetButtonDown( "Jump" ) && isGrounded ) { _velocity.y = Mathf.Sqrt( jumpHeight * -2f * gravity ); }
    }

    void ApplyGravity() {
        _velocity.y += gravity * Time.deltaTime;
        _playerController.Move( _velocity * Time.deltaTime );
    }
}

I hope this helps someone,

Cheers!

1 Like

This is exactly what I was looking for Thanks : )

my life has been complete with this thank you so much bro but uhh you know the drill; hippidy hoppidy your code is now my property :smile: