JS to C# Conversion

Hi, I found a old 3rd person controller in Unity that do exactly what I need, and I am tryng to convert to C# but have some error that I dont know how fix, can anyone help me please?

this is the original code in .js:

public var walkMaxAnimationSpeed : float = 0.75;
public var trotMaxAnimationSpeed : float = 1.0;
public var runMaxAnimationSpeed : float = 1.0;
public var jumpAnimationSpeed : float = 1.15;
public var landAnimationSpeed : float = 1.0;

private var _animation : Animation;

enum CharacterState {
    Idle = 0,
    Walking = 1,
    Trotting = 2,
    Running = 3,
    Jumping = 4,
}

private var _characterState : CharacterState;

// The speed when walking
var walkSpeed = 2.0;
// after trotAfterSeconds of walking we trot with trotSpeed
var trotSpeed = 4.0;
// when pressing "Fire3" button (cmd) we start running
var runSpeed = 6.0;

var inAirControlAcceleration = 3.0;

// How high do we jump when pressing jump and letting go immediately
var jumpHeight = 0.5;

// The gravity for the character
var gravity = 20.0;
// The gravity in controlled descent mode
var speedSmoothing = 10.0;
var rotateSpeed = 500.0;
var trotAfterSeconds = 3.0;

var canJump = true;

private var jumpRepeatTime = 0.05;
private var jumpTimeout = 0.15;
private var groundedTimeout = 0.25;

// The camera doesnt start following the target immediately but waits for a split second to avoid too much waving around.
private var lockCameraTimer = 0.0;

// The current move direction in x-z
private var moveDirection = Vector3.zero;
// The current vertical speed
private var verticalSpeed = 0.0;
// The current x-z move speed
private var moveSpeed = 0.0;

// The last collision flags returned from controller.Move
private var collisionFlags : CollisionFlags;

// Are we jumping? (Initiated with jump button and not grounded yet)
private var jumping = false;
private var jumpingReachedApex = false;

// Are we moving backwards (This locks the camera to not do a 180 degree spin)
private var movingBack = false;
// Is the user pressing any keys?
private var isMoving = false;
// When did the user start walking (Used for going into trot after a while)
private var walkTimeStart = 0.0;
// Last time the jump button was clicked down
private var lastJumpButtonTime = -10.0;
// Last time we performed a jump
private var lastJumpTime = -1.0;


// the height we jumped from (Used to determine for how long to apply extra jump power after jumping.)
private var lastJumpStartHeight = 0.0;


private var inAirVelocity = Vector3.zero;

private var lastGroundedTime = 0.0;


private var isControllable = true;

function Awake ()
{
    moveDirection = transform.TransformDirection(Vector3.forward);
         
}


function UpdateSmoothedMovementDirection ()
{
    var cameraTransform = Camera.main.transform;
    var grounded = IsGrounded();
 
    // Forward vector relative to the camera along the x-z plane 
    var forward = cameraTransform.TransformDirection(Vector3.forward);
    forward.y = 0;
    forward = forward.normalized;

    // Right vector relative to the camera
    // Always orthogonal to the forward vector
    var right = Vector3(forward.z, 0, -forward.x);

    var v = Input.GetAxisRaw("Vertical");
    var h = Input.GetAxisRaw("Horizontal");

    // Are we moving backwards or looking backwards
    if (v < -0.2)
        movingBack = true;
    else
        movingBack = false;
 
    var wasMoving = isMoving;
    isMoving = Mathf.Abs (h) > 0.1 || Mathf.Abs (v) > 0.1;
     
    // Target direction relative to the camera
    var targetDirection = h * right + v * forward;
 
    // Grounded controls
    if (grounded)
    {
        // Lock camera for short period when transitioning moving & standing still
        lockCameraTimer += Time.deltaTime;
        if (isMoving != wasMoving)
            lockCameraTimer = 0.0;

        // We store speed and direction seperately,
        // so that when the character stands still we still have a valid forward direction
        // moveDirection is always normalized, and we only update it if there is user input.
        if (targetDirection != Vector3.zero)
        {
            // If we are really slow, just snap to the target direction
            if (moveSpeed < walkSpeed * 0.9 && grounded)
            {
                moveDirection = targetDirection.normalized;
            }
            // Otherwise smoothly turn towards it
            else
            {
                moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);
             
                moveDirection = moveDirection.normalized;
            }
        }
     
        // Smooth the speed based on the current target direction
        var curSmooth = speedSmoothing * Time.deltaTime;
     
        // Choose target speed
        //* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways
        var targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0);
 
        _characterState = CharacterState.Idle;
     
        // Pick speed modifier
        if (Input.GetKey (KeyCode.LeftShift) || Input.GetKey (KeyCode.RightShift))
        {
            targetSpeed *= runSpeed;
            _characterState = CharacterState.Running;
        }
        else if (Time.time - trotAfterSeconds > walkTimeStart)
        {
            targetSpeed *= trotSpeed;
            _characterState = CharacterState.Trotting;
        }
        else
        {
            targetSpeed *= walkSpeed;
            _characterState = CharacterState.Walking;
        }
     
        moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);
     
        // Reset walk time start when we slow down
        if (moveSpeed < walkSpeed * 0.3)
            walkTimeStart = Time.time;
    }
    // In air controls
    else
    {
        // Lock camera while in air
        if (jumping)
            lockCameraTimer = 0.0;

        if (isMoving)
            inAirVelocity += targetDirection.normalized * Time.deltaTime * inAirControlAcceleration;
    }
 

     
}


function ApplyJumping ()
{
    // Prevent jumping too fast after each other
    if (lastJumpTime + jumpRepeatTime > Time.time)
        return;

    if (IsGrounded()) {
        // Jump
        // - Only when pressing the button down
        // - With a timeout so you can press the button slightly before landing     
        if (canJump && Time.time < lastJumpButtonTime + jumpTimeout) {
            verticalSpeed = CalculateJumpVerticalSpeed (jumpHeight);
            SendMessage("DidJump", SendMessageOptions.DontRequireReceiver);
        }
    }
}


function ApplyGravity ()
{
    if (isControllable)    // don't move player at all if not controllable.
    {
        // Apply gravity
        var jumpButton = Input.GetButton("Jump");
     
     
        // When we reach the apex of the jump we send out a message
        if (jumping && !jumpingReachedApex && verticalSpeed <= 0.0)
        {
            jumpingReachedApex = true;
            SendMessage("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
        }
 
        if (IsGrounded ())
            verticalSpeed = 0.0;
        else
            verticalSpeed -= gravity * Time.deltaTime;
    }
}

function CalculateJumpVerticalSpeed (targetJumpHeight : float)
{
    // From the jump height and gravity we deduce the upwards speed
    // for the character to reach at the apex.
    return Mathf.Sqrt(2 * targetJumpHeight * gravity);
}

function DidJump ()
{
    jumping = true;
    jumpingReachedApex = false;
    lastJumpTime = Time.time;
    lastJumpStartHeight = transform.position.y;
    lastJumpButtonTime = -10;
 
    _characterState = CharacterState.Jumping;
}

function Update() {
 
    if (!isControllable)
    {
        // kill all inputs if not controllable.
        Input.ResetInputAxes();
    }

    if (Input.GetButtonDown ("Jump"))
    {
        lastJumpButtonTime = Time.time;
    }

    UpdateSmoothedMovementDirection();
 
    // Apply gravity
    // - extra power jump modifies gravity
    // - controlledDescent mode modifies gravity
    ApplyGravity ();

    // Apply jumping logic
    ApplyJumping ();
 
    // Calculate actual motion
    var movement = moveDirection * moveSpeed + Vector3 (0, verticalSpeed, 0) + inAirVelocity;
    movement *= Time.deltaTime;
 
    // Move the controller
    var controller : CharacterController = GetComponent(CharacterController);
    collisionFlags = controller.Move(movement);
 
    // Set rotation to the move direction
    if (IsGrounded())
    {
     
        transform.rotation = Quaternion.LookRotation(moveDirection);
         
    } 
    else
    {
        var xzMove = movement;
        xzMove.y = 0;
        if (xzMove.sqrMagnitude > 0.001)
        {
            transform.rotation = Quaternion.LookRotation(xzMove);
        }
    } 
 
    // We are in jump mode but just became grounded
    if (IsGrounded())
    {
        lastGroundedTime = Time.time;
        inAirVelocity = Vector3.zero;
        if (jumping)
        {
            jumping = false;
            SendMessage("DidLand", SendMessageOptions.DontRequireReceiver);
        }
    }
}

function OnControllerColliderHit (hit : ControllerColliderHit )
{
//    Debug.DrawRay(hit.point, hit.normal);
    if (hit.moveDirection.y > 0.01)
        return;
}

function GetSpeed () {
    return moveSpeed;
}

function IsJumping () {
    return jumping;
}

function IsGrounded () {
    return (collisionFlags & CollisionFlags.CollidedBelow) != 0;
}

function GetDirection () {
    return moveDirection;
}

function IsMovingBackwards () {
    return movingBack;
}

function GetLockCameraTimer ()
{
    return lockCameraTimer;
}

function IsMoving ()  : boolean
{
    return Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal")) > 0.5;
}

function HasJumpReachedApex ()
{
    return jumpingReachedApex;
}

function IsGroundedWithTimeout ()
{
    return lastGroundedTime + groundedTimeout > Time.time;
}

function Reset ()
{
    gameObject.tag = "Player";
}

this is what I translated with help with this site Convert unity javascript (unityscript) to C#

using UnityEngine;
using System.Collections;

public class Controller : MonoBehaviour {

    public float walkMaxAnimationSpeed = 0.75f;
    public float trotMaxAnimationSpeed = 1.0f;
    public float runMaxAnimationSpeed = 1.0f;
    public float jumpAnimationSpeed = 1.15f;
    public float landAnimationSpeed = 1.0f;

    private Animation _animation;

    enum CharacterState {
        Idle = 0,
        Walking = 1,
        Trotting = 2,
        Running = 3,
        Jumping = 4,
    }

    private CharacterState _characterState;

    // The speed when walking
    float walkSpeed= 2.0f;
    // after trotAfterSeconds of walking we trot with trotSpeed
    float trotSpeed= 4.0f;
    // when pressing "Fire3" button (cmd) we start running
    float runSpeed= 6.0f;

    float inAirControlAcceleration= 3.0f;

    // How high do we jump when pressing jump and letting go immediately
    float jumpHeight= 0.5f;

    // The gravity for the character
    float gravity= 20.0f;
    // The gravity in controlled descent mode
    float speedSmoothing= 10.0f;
    float rotateSpeed= 500.0f;
    float trotAfterSeconds= 3.0f;

    bool canJump= true;

    private float jumpRepeatTime= 0.05f;
    private float jumpTimeout= 0.15f;
    private float groundedTimeout= 0.25f;

    // The camera doesnt start following the target immediately but waits for a split second to avoid too much waving around.
    private float lockCameraTimer= 0.0f;

    // The current move direction in x-z
    private Vector3 moveDirection= Vector3.zero;
    // The current vertical speed
    private float verticalSpeed= 0.0f;
    // The current x-z move speed
    private float moveSpeed= 0.0f;

    // The last collision flags returned from controller.Move
    private CollisionFlags collisionFlags;

    // Are we jumping? (Initiated with jump button and not grounded yet)
    private bool jumping= false;
    private bool jumpingReachedApex= false;

    // Are we moving backwards (This locks the camera to not do a 180 degree spin)
    private bool movingBack= false;
    // Is the user pressing any keys?
    private bool isMoving= false;
    // When did the user start walking (Used for going into trot after a while)
    private float walkTimeStart= 0.0f;
    // Last time the jump button was clicked down
    private float lastJumpButtonTime= -10.0f;
    // Last time we performed a jump
    private float lastJumpTime= -1.0f;


    // the height we jumped from (Used to determine for how long to apply extra jump power after jumping.)
    private float lastJumpStartHeight= 0.0f;


    private Vector3 inAirVelocity= Vector3.zero;

    private float lastGroundedTime= 0.0f;


    private bool isControllable= true;

    void  Awake (){
        moveDirection = transform.TransformDirection(Vector3.forward);
    }


    void  UpdateSmoothedMovementDirection (){
        Transform cameraTransform= Camera.main.transform;
        FIXME_VAR_TYPE grounded= IsGrounded();

        // Forward vector relative to the camera along the x-z plane 
        Vector3 forward= cameraTransform.TransformDirection(Vector3.forward);
        forward.y = 0;
        forward = forward.normalized;

        // Right vector relative to the camera
        // Always orthogonal to the forward vector
        Vector3 right= new Vector3(forward.z, 0, -forward.x);

        float v= Input.GetAxisRaw("Vertical");
        float h= Input.GetAxisRaw("Horizontal");

        // Are we moving backwards or looking backwards
        if (v < -0.2f)
            movingBack = true;
        else
            movingBack = false;

        float wasMoving= isMoving;
        isMoving = Mathf.Abs (h) > 0.1f || Mathf.Abs (v) > 0.1f;

        // Target direction relative to the camera
        Vector3 targetDirection= h * right + v * forward;

        // Grounded controls
        if (grounded)
        {
            // Lock camera for short period when transitioning moving & standing still
            lockCameraTimer += Time.deltaTime;
            if (isMoving != wasMoving)
                lockCameraTimer = 0.0f;

            // We store speed and direction seperately,
            // so that when the character stands still we still have a valid forward direction
            // moveDirection is always normalized, and we only update it if there is user input.
            if (targetDirection != Vector3.zero)
            {
                // If we are really slow, just snap to the target direction
                if (moveSpeed < walkSpeed * 0.9f && grounded)
                {
                    moveDirection = targetDirection.normalized;
                }
                // Otherwise smoothly turn towards it
                else
                {
                    moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);

                    moveDirection = moveDirection.normalized;
                }
            }

            // Smooth the speed based on the current target direction
            float curSmooth= speedSmoothing * Time.deltaTime;

            // Choose target speed
            //* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways
            float targetSpeed= Mathf.Min(targetDirection.magnitude, 1.0f);

            _characterState = CharacterState.Idle;

            // Pick speed modifier
            if (Input.GetKey (KeyCode.LeftShift) || Input.GetKey (KeyCode.RightShift))
            {
                targetSpeed *= runSpeed;
                _characterState = CharacterState.Running;
            }
            else if (Time.time - trotAfterSeconds > walkTimeStart)
            {
                targetSpeed *= trotSpeed;
                _characterState = CharacterState.Trotting;
            }
            else
            {
                targetSpeed *= walkSpeed;
                _characterState = CharacterState.Walking;
            }

            moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);

            // Reset walk time start when we slow down
            if (moveSpeed < walkSpeed * 0.3f)
                walkTimeStart = Time.time;
        }
        // In air controls
        else
        {
            // Lock camera while in air
            if (jumping)
                lockCameraTimer = 0.0f;

            if (isMoving)
                inAirVelocity += targetDirection.normalized * Time.deltaTime * inAirControlAcceleration;
        }



    }


    void  ApplyJumping (){
        // Prevent jumping too fast after each other
        if (lastJumpTime + jumpRepeatTime > Time.time)
            return;

        if (IsGrounded()) {
            // Jump
            // - Only when pressing the button down
            // - With a timeout so you can press the button slightly before landing     
            if (canJump && Time.time < lastJumpButtonTime + jumpTimeout) {
                verticalSpeed = CalculateJumpVerticalSpeed (jumpHeight);
                SendMessage("DidJump", SendMessageOptions.DontRequireReceiver);
            }
        }
    }


    void  ApplyGravity (){
        if (isControllable)    // don't move player at all if not controllable.
        {
            // Apply gravity
            bool jumpButton= Input.GetButton("Jump");


            // When we reach the apex of the jump we send out a message
            if (jumping && !jumpingReachedApex && verticalSpeed <= 0.0f)
            {
                jumpingReachedApex = true;
                SendMessage("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
            }

            if (IsGrounded ())
                verticalSpeed = 0.0f;
            else
                verticalSpeed -= gravity * Time.deltaTime;
        }
    }

    void  CalculateJumpVerticalSpeed ( float targetJumpHeight  ){
        // From the jump height and gravity we deduce the upwards speed
        // for the character to reach at the apex.
        return Mathf.Sqrt(2 * targetJumpHeight * gravity);
    }

    void  DidJump (){
        jumping = true;
        jumpingReachedApex = false;
        lastJumpTime = Time.time;
        lastJumpStartHeight = transform.position.y;
        lastJumpButtonTime = -10;

        _characterState = CharacterState.Jumping;
    }

    void  Update (){

        if (!isControllable)
        {
            // kill all inputs if not controllable.
            Input.ResetInputAxes();
        }

        if (Input.GetButtonDown ("Jump"))
        {
            lastJumpButtonTime = Time.time;
        }

        UpdateSmoothedMovementDirection();

        // Apply gravity
        // - extra power jump modifies gravity
        // - controlledDescent mode modifies gravity
        ApplyGravity ();

        // Apply jumping logic
        ApplyJumping ();

        // Calculate actual motion
        Vector3 movement= moveDirection * moveSpeed + new Vector3 (0, verticalSpeed, 0) + inAirVelocity;
        movement *= Time.deltaTime;

        // Move the controller
        CharacterController controller = GetComponent<CharacterController>();
        collisionFlags = controller.Move(movement);

        // Set rotation to the move direction
        if (IsGrounded())
        {

            transform.rotation = Quaternion.LookRotation(moveDirection);

        } 
        else
        {
            Vector3 xzMove= movement;
            xzMove.y = 0;
            if (xzMove.sqrMagnitude > 0.001f)
            {
                transform.rotation = Quaternion.LookRotation(xzMove);
            }
        } 

        // We are in jump mode but just became grounded
        if (IsGrounded())
        {
            lastGroundedTime = Time.time;
            inAirVelocity = Vector3.zero;
            if (jumping)
            {
                jumping = false;
                SendMessage("DidLand", SendMessageOptions.DontRequireReceiver);
            }
        }
    }

    void  OnControllerColliderHit ( ControllerColliderHit hit   ){
        //    Debug.DrawRay(hit.point, hit.normal);
        if (hit.moveDirection.y > 0.01f)
            return;
    }

    void  GetSpeed (){
        return moveSpeed;
    }

    void  IsJumping (){
        return jumping;
    }

    void  IsGrounded (){
        return (collisionFlags & CollisionFlags.CollidedBelow) != 0;
    }

    void  GetDirection (){
        return moveDirection;
    }

    void  IsMovingBackwards (){
        return movingBack;
    }

    void  GetLockCameraTimer (){
        return lockCameraTimer;
    }

    bool IsMoving (){
        return Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal")) > 0.5f;
    }

    void  HasJumpReachedApex (){
        return jumpingReachedApex;
    }

    void  IsGroundedWithTimeout (){
        return lastGroundedTime + groundedTimeout > Time.time;
    }

    void  Reset (){
        gameObject.tag = "Player";
    }


}

and this is the errors I am receiving:

Assets/Controller.cs(101,22): error CS0029: Cannot implicitly convert type void' to bool’
Assets/Controller.cs(121,23): error CS0029: Cannot implicitly convert type bool' to float’
Assets/Controller.cs(132,29): error CS0019: Operator !=' cannot be applied to operands of type bool’ and float' Assets/Controller.cs(207,17): error CS0029: Cannot implicitly convert type void’ to bool' Assets/Controller.cs(212,33): error CS0029: Cannot implicitly convert type void’ to float' Assets/Controller.cs(233,25): error CS0029: Cannot implicitly convert type void’ to bool' Assets/Controller.cs(243,17): error CS0127: Controller.CalculateJumpVerticalSpeed(float)‘: A return keyword must not be followed by any expression when method returns void
Assets/Controller.cs(243,17): error CS0029: Cannot implicitly convert type float' to void’
Assets/Controller.cs(288,17): error CS0029: Cannot implicitly convert type void' to bool’
Assets/Controller.cs(305,17): error CS0029: Cannot implicitly convert type void' to bool’
Assets/Controller.cs(324,17): error CS0127: Controller.GetSpeed()': A return keyword must not be followed by any expression when method returns void Assets/Controller.cs(324,17): error CS0029: Cannot implicitly convert type float’ to void' Assets/Controller.cs(328,17): error CS0127: Controller.IsJumping()‘: A return keyword must not be followed by any expression when method returns void
Assets/Controller.cs(328,17): error CS0029: Cannot implicitly convert type bool' to void’
Assets/Controller.cs(332,17): error CS0127: Controller.IsGrounded()': A return keyword must not be followed by any expression when method returns void Assets/Controller.cs(332,17): error CS0029: Cannot implicitly convert type bool’ to void' Assets/Controller.cs(336,17): error CS0127: Controller.GetDirection()‘: A return keyword must not be followed by any expression when method returns void
Assets/Controller.cs(336,17): error CS0029: Cannot implicitly convert type UnityEngine.Vector3' to void’
Assets/Controller.cs(340,17): error CS0127: Controller.IsMovingBackwards()': A return keyword must not be followed by any expression when method returns void Assets/Controller.cs(340,17): error CS0029: Cannot implicitly convert type bool’ to void' Assets/Controller.cs(344,17): error CS0127: Controller.GetLockCameraTimer()‘: A return keyword must not be followed by any expression when method returns void
Assets/Controller.cs(344,17): error CS0029: Cannot implicitly convert type float' to void’
Assets/Controller.cs(352,17): error CS0127: Controller.HasJumpReachedApex()': A return keyword must not be followed by any expression when method returns void Assets/Controller.cs(352,17): error CS0029: Cannot implicitly convert type bool’ to void' Assets/Controller.cs(356,17): error CS0127: Controller.IsGroundedWithTimeout()‘: A return keyword must not be followed by any expression when method returns void
Assets/Controller.cs(356,17): error CS0029: Cannot implicitly convert type bool' to void’

I know is a lot of erros but some are repeated for the same problem… I asking for help because I dont know how to solve this problems, the problems I know I already solved… thanks in advance!

Note: In JS all works fine, I want convert to C# because JS will not be avaible in the future.

Happy holidays- consider this my gift to you. In the future, please read some basic tutorials on C# and programming before trying to handle a script conversion- this had about 30 problems and every single one of them were beginner-level mistakes. Overlooking one or two is one thing, but… jinkies… the error messages also said exactly what was wrong and how to fix it (in 30 different places).

Automated conversions systems don’t work.

using UnityEngine;
using System.Collections;

public class Controller : MonoBehaviour
{
    public float walkMaxAnimationSpeed = 0.75f;
    public float trotMaxAnimationSpeed = 1.0f;
    public float runMaxAnimationSpeed = 1.0f;
    public float jumpAnimationSpeed = 1.15f;
    public float landAnimationSpeed = 1.0f;

    private Animation _animation;

    private enum CharacterState
    {
        Idle = 0,
        Walking = 1,
        Trotting = 2,
        Running = 3,
        Jumping = 4,
    };

    private CharacterState _characterState;

    // The speed when walking
    private float walkSpeed = 2.0f;
    // after trotAfterSeconds of walking we trot with trotSpeed
    private float trotSpeed = 4.0f;
    // when pressing "Fire3" button (cmd) we start running
    private float runSpeed = 6.0f;

    private float inAirControlAcceleration = 3.0f;

    // How high do we jump when pressing jump and letting go immediately
    private float jumpHeight = 0.5f;

    // The gravity for the character
    private float gravity = 20.0f;
    // The gravity in controlled descent mode
    private float speedSmoothing = 10.0f;
    private float rotateSpeed = 500.0f;
    private float trotAfterSeconds = 3.0f;

    bool canJump = true;

    private float jumpRepeatTime = 0.05f;
    private float jumpTimeout = 0.15f;
    private float groundedTimeout = 0.25f;

    // The camera doesnt start following the target immediately but waits for a split second to avoid too much waving around.
    private float lockCameraTimer = 0.0f;

    // The current move direction in x-z
    private Vector3 moveDirection = Vector3.zero;
    // The current vertical speed
    private float verticalSpeed = 0.0f;
    // The current x-z move speed
    private float moveSpeed = 0.0f;

    // The last collision flags returned from controller.Move
    private CollisionFlags collisionFlags;

    // Are we jumping? (Initiated with jump button and not grounded yet)
    private bool jumping = false;
    private bool jumpingReachedApex = false;

    // Are we moving backwards (This locks the camera to not do a 180 degree spin)
    private bool movingBack = false;
    // Is the user pressing any keys?
    private bool isMoving = false;
    // When did the user start walking (Used for going into trot after a while)
    private float walkTimeStart = 0.0f;
    // Last time the jump button was clicked down
    private float lastJumpButtonTime = -10.0f;
    // Last time we performed a jump
    private float lastJumpTime = -1.0f;

    // the height we jumped from (Used to determine for how long to apply extra jump power after jumping.)
    private float lastJumpStartHeight = 0.0f;

    private Vector3 inAirVelocity = Vector3.zero;

    private float lastGroundedTime = 0.0f;

    private bool isControllable = true;

    private void Awake()
    {
        moveDirection = transform.TransformDirection(Vector3.forward);
    }

    private void UpdateSmoothedMovementDirection()
    {
        Transform cameraTransform = Camera.main.transform;
        bool grounded = IsGrounded();

        // Forward vector relative to the camera along the x-z plane
        Vector3 forward = cameraTransform.TransformDirection(Vector3.forward);
        forward.y = 0;
        forward = forward.normalized;

        // Right vector relative to the camera
        // Always orthogonal to the forward vector
        Vector3 right = new Vector3(forward.z, 0, -forward.x);

        float v = Input.GetAxisRaw("Vertical");
        float h = Input.GetAxisRaw("Horizontal");

        // Are we moving backwards or looking backwards
        if (v < -0.2f)
            movingBack = true;
        else
            movingBack = false;

        bool wasMoving = isMoving;
        isMoving = Mathf.Abs(h) > 0.1f || Mathf.Abs(v) > 0.1f;

        // Target direction relative to the camera
        Vector3 targetDirection = h * right + v * forward;

        // Grounded controls
        if (grounded)
        {
            // Lock camera for short period when transitioning moving & standing still
            lockCameraTimer += Time.deltaTime;
            if (isMoving != wasMoving)
                lockCameraTimer = 0.0f;

            // We store speed and direction seperately,
            // so that when the character stands still we still have a valid forward direction
            // moveDirection is always normalized, and we only update it if there is user input.
            if (targetDirection != Vector3.zero)
            {
                // If we are really slow, just snap to the target direction
                if (moveSpeed < walkSpeed * 0.9f && grounded)
                {
                    moveDirection = targetDirection.normalized;
                }
                // Otherwise smoothly turn towards it
                else
                {
                    moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);

                    moveDirection = moveDirection.normalized;
                }
            }

            // Smooth the speed based on the current target direction
            float curSmooth = speedSmoothing * Time.deltaTime;

            // Choose target speed
            //* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways
            float targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0f);

            _characterState = CharacterState.Idle;

            // Pick speed modifier
            if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift))
            {
                targetSpeed *= runSpeed;
                _characterState = CharacterState.Running;
            }
            else if (Time.time - trotAfterSeconds > walkTimeStart)
            {
                targetSpeed *= trotSpeed;
                _characterState = CharacterState.Trotting;
            }
            else
            {
                targetSpeed *= walkSpeed;
                _characterState = CharacterState.Walking;
            }

            moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);

            // Reset walk time start when we slow down
            if (moveSpeed < walkSpeed * 0.3f)
                walkTimeStart = Time.time;
        }
        // In air controls
        else
        {
            // Lock camera while in air
            if (jumping)
                lockCameraTimer = 0.0f;

            if (isMoving)
                inAirVelocity += targetDirection.normalized * Time.deltaTime * inAirControlAcceleration;
        }
    }

    private void ApplyJumping()
    {
        // Prevent jumping too fast after each other
        if (lastJumpTime + jumpRepeatTime > Time.time)
            return;

        if (IsGrounded())
        {
            // Jump
            // - Only when pressing the button down
            // - With a timeout so you can press the button slightly before landing 
            if (canJump && Time.time < lastJumpButtonTime + jumpTimeout)
            {
                verticalSpeed = CalculateJumpVerticalSpeed(jumpHeight);
                SendMessage("DidJump", SendMessageOptions.DontRequireReceiver);
            }
        }
    }

    private void ApplyGravity()
    {
        if (isControllable)    // don't move player at all if not controllable.
        {
            // Apply gravity
            bool jumpButton = Input.GetButton("Jump");


            // When we reach the apex of the jump we send out a message
            if (jumping && !jumpingReachedApex && verticalSpeed <= 0.0f)
            {
                jumpingReachedApex = true;
                SendMessage("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
            }

            if (IsGrounded())
                verticalSpeed = 0.0f;
            else
                verticalSpeed -= gravity * Time.deltaTime;
        }
    }

    private float CalculateJumpVerticalSpeed(float targetJumpHeight)
    {
        // From the jump height and gravity we deduce the upwards speed
        // for the character to reach at the apex.
        return Mathf.Sqrt(2 * targetJumpHeight * gravity);
    }

    private void DidJump()
    {
        jumping = true;
        jumpingReachedApex = false;
        lastJumpTime = Time.time;
        lastJumpStartHeight = transform.position.y;
        lastJumpButtonTime = -10;

        _characterState = CharacterState.Jumping;
    }

    private void Update()
    {

        if (!isControllable)
        {
            // kill all inputs if not controllable.
            Input.ResetInputAxes();
        }

        if (Input.GetButtonDown("Jump"))
        {
            lastJumpButtonTime = Time.time;
        }

        UpdateSmoothedMovementDirection();

        // Apply gravity
        // - extra power jump modifies gravity
        // - controlledDescent mode modifies gravity
        ApplyGravity();

        // Apply jumping logic
        ApplyJumping();

        // Calculate actual motion
        Vector3 movement = moveDirection * moveSpeed + new Vector3(0, verticalSpeed, 0) + inAirVelocity;
        movement *= Time.deltaTime;

        // Move the controller
        CharacterController controller = GetComponent<CharacterController>();
        collisionFlags = controller.Move(movement);

        // Set rotation to the move direction
        if (IsGrounded())
        {
            transform.rotation = Quaternion.LookRotation(moveDirection);
        }
        else
        {
            Vector3 xzMove = movement;
            xzMove.y = 0;
            if (xzMove.sqrMagnitude > 0.001f)
            {
                transform.rotation = Quaternion.LookRotation(xzMove);
            }
        }

        // We are in jump mode but just became grounded
        if (IsGrounded())
        {
            lastGroundedTime = Time.time;
            inAirVelocity = Vector3.zero;
            if (jumping)
            {
                jumping = false;
                SendMessage("DidLand", SendMessageOptions.DontRequireReceiver);
            }
        }
    }

    public void OnControllerColliderHit(ControllerColliderHit hit)
    {
        //    Debug.DrawRay(hit.point, hit.normal);
        if (hit.moveDirection.y > 0.01f)
            return;
    }

    public float GetSpeed()
    {
        return moveSpeed;
    }

    public bool IsJumping()
    {
        return jumping;
    }

    public bool IsGrounded()
    {
        return (collisionFlags & CollisionFlags.CollidedBelow) != 0;
    }

    public Vector3 GetDirection()
    {
        return moveDirection;
    }

    public bool IsMovingBackwards()
    {
        return movingBack;
    }

    public float GetLockCameraTimer()
    {
        return lockCameraTimer;
    }

    public bool IsMoving()
    {
        return Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal")) > 0.5f;
    }

    public bool HasJumpReachedApex()
    {
        return jumpingReachedApex;
    }

    public bool IsGroundedWithTimeout()
    {
        return lastGroundedTime + groundedTimeout > Time.time;
    }

    public void Reset()
    {
        gameObject.tag = "Player";
    }
}

I haven’t tested this, as I have nothing that uses this style of character controller, but it should compile at least.

5 Likes

WOW thanks for the help, now I understand what I have to do if this errors happen again!, thanks a lot!