Paste
Of Code


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

public class PlayerController : MonoBehaviour
{

    [Header("References")]
    public PlayerControllerStats ControllStats;
    [SerializeField] private Collider2D FeetColl;
    [SerializeField] private Collider2D BodyColl;
    public Rigidbody2D rb;
    private PlayerControls playerControls;

    //movement vars
    private Vector2 MoveVelocity;
    private bool isFacingRight;

    //Collision check vars
    private RaycastHit2D GroundHit;
    private RaycastHit2D HeadHit;
    private bool IsGrounded;
    private bool BumpedHead;

    //Jump vars
    public float VerticalVelocity { get; private set; }
    private bool IsJumping;
    private bool IsFastFalling;
    private bool IsFalling;
    private float FastFallTime;
    private float FastFallReleaseSpeed;
    private int NumberOfJumpsUsed;

    //Apex vars
    private float ApexPoint;
    private float TimePastApexThreshold;
    private bool IsPastApexThreshold;

    //Jump buffer vars
    private float JumpBufferTimer;
    private bool JumpReleasedDuringBuffer;

    //coyote time vars
    private float CoyoteTimer;



    private void Awake()
    {
        playerControls = new PlayerControls();
        isFacingRight = true;
    }
    private void OnEnable()
    {
        playerControls.Enable();
    }
    private void OnDisable()
    {
        playerControls.Disable();
    }

    void FixedUpdate()
    {
        CollisionChecks();

        Jump();

        if(IsGrounded)
        {
            Move(ControllStats.GroundAcceleration, ControllStats.GroundDeceleration, playerControls.mainActions.Move.ReadValue<Vector2>());
        }
        else
        {
            Move(ControllStats.AirAcceleration, ControllStats.AirDeceleration, playerControls.mainActions.Move.ReadValue<Vector2>());

        }
    }

    private void Update()
    {
        CountTimers();
        JumpChecks();
    }


    private void JumpChecks()
    {
        //WHEN WE PRESS THE JUMP BUTTON
        if(playerControls.mainActions.Jump.WasPressedThisFrame())
        {
            JumpBufferTimer = ControllStats.JumpBufferTime;
            JumpReleasedDuringBuffer = false;
        }

        //WHEN WE RELEASE THE JUMP BUTTON
        if(playerControls.mainActions.Jump.WasReleasedThisFrame())
        {
            if(JumpBufferTimer > 0f)
            {
            JumpReleasedDuringBuffer = true;
            }

            if(IsJumping && VerticalVelocity > 0f)
            {
                if(IsPastApexThreshold)
                {
                    IsPastApexThreshold = false;
                    IsFastFalling = true;
                    FastFallTime = ControllStats.TimeForUpwadsCancel;
                    VerticalVelocity = 0f;
                }
                else
                {
                    IsFastFalling = true;
                    FastFallReleaseSpeed = VerticalVelocity;
                }
            }
        }

        //INITIATE JUMP WITH JUMP BUFFERING AND COYOTE TIME
        if (JumpBufferTimer > 0f && !IsJumping && (IsGrounded || CoyoteTimer > 0f))
        {
            InitiateJump(1);

            if (JumpReleasedDuringBuffer)
            {
                IsFastFalling = true;
                FastFallReleaseSpeed = VerticalVelocity;
            }
        }

        //DOUBLE JUMP
        else if (JumpBufferTimer > 0f && IsJumping && NumberOfJumpsUsed < ControllStats.NumberOfJumpsAllowed)
        {
            IsFastFalling = false;
            InitiateJump(1);
        }

        //AIR JUMP AFTER COYOTE TIME LAPSED
        else if (JumpBufferTimer > 0f && IsJumping && NumberOfJumpsUsed < ControllStats.NumberOfJumpsAllowed -1)
        {
            IsFastFalling = false;
            InitiateJump(2);
        }

        //LANDED
        if ((IsJumping || IsFalling) && IsGrounded && VerticalVelocity <= 0f)
        {
            IsJumping = false;
            IsFalling = false;
            IsFastFalling = false;
            FastFallTime = 0f;
            IsPastApexThreshold = false;
            NumberOfJumpsUsed = 0;

            VerticalVelocity = Physics2D.gravity.y;
        }

    }

    private void InitiateJump(int NumberOfJumpsUsed)
    {
        if(!IsJumping)
        {
            IsJumping = true;
        }

        JumpBufferTimer = 0f;
        this.NumberOfJumpsUsed += NumberOfJumpsUsed;
        VerticalVelocity = ControllStats.InitialJumpVelocity;

    }

    private void Jump()
    {
        //APPLY GRAVITY WHILE JUMPING
        if(IsJumping)
        {
        //CHECK FOR HEAD BUMP
            if(BumpedHead)
            {
                IsFastFalling = true;
            }


            //GRAVITY ON ASCENING
            if(VerticalVelocity >= 0f)
            {
                //APEX CONTROLLS
                ApexPoint = Mathf.InverseLerp(ControllStats.InitialJumpVelocity, 0f, VerticalVelocity);

                if(ApexPoint > ControllStats.ApexThreshold)
                {
                    if(!IsPastApexThreshold)
                    {
                        IsPastApexThreshold = true;
                        TimePastApexThreshold = 0f;
                    }

                    if(IsPastApexThreshold)
                    {
                        TimePastApexThreshold += Time.fixedDeltaTime;

                        if(TimePastApexThreshold <ControllStats.ApexHangTime)
                        {
                            VerticalVelocity = 0f;

                        }
                        else
                        {
                            VerticalVelocity = -0.01f;
                        }
                    }

                }
            }

            //GRAVITY ON ASCENDING BUT NOT PAST APEX THRESHOLD
            else
            {
                VerticalVelocity += ControllStats.Gravity * Time.fixedDeltaTime;

                if(IsPastApexThreshold)
                {
                    IsPastApexThreshold = false;
                }
            }
        }

        //GRAVITY ON DESCENDING
        else if(!IsFastFalling)
        {
            VerticalVelocity += ControllStats.GravityOnReleaseMultiplier * Time.fixedDeltaTime;
        }
        else if(VerticalVelocity < 0f)
        {
            if(!IsFalling)
            {
            IsFalling = true;
            }
        }

        //JUMP CUT
        if(IsFastFalling)
        {
            if(FastFallTime >= ControllStats.TimeForUpwadsCancel)
            {
                VerticalVelocity = ControllStats.Gravity * ControllStats.GravityOnReleaseMultiplier * Time.fixedDeltaTime;
            }

            else if(FastFallTime < ControllStats.TimeForUpwadsCancel)
            {
                VerticalVelocity = Mathf.Lerp(FastFallReleaseSpeed, 0f, (FastFallTime / ControllStats.TimeForUpwadsCancel));
            }

            FastFallTime += Time.fixedDeltaTime;
        }

        //NORMAL GRAVITY WHILE FALLING
        if(!IsGrounded && !IsJumping)
        {
            if(!IsFalling)
            {
                IsFalling = true;
            }

            VerticalVelocity += ControllStats.Gravity * Time.fixedDeltaTime;
        }

        //CLAMP FALL SPEED
        VerticalVelocity = Mathf.Clamp(VerticalVelocity, -ControllStats.MaxFallSpeed, 50);

        rb.velocity = new Vector2(rb.velocity.x, VerticalVelocity);
    }


    private void CountTimers()
    {
        JumpBufferTimer -= Time.deltaTime;

        if(!IsGrounded)
        {
            CoyoteTimer -= Time.deltaTime;
        }
        else
        {
            CoyoteTimer = ControllStats.JumpCoyoteTime;
        }
    }


    private void Move(float Acceleration, float Deceleration, Vector2 MoveInput)
    {
        if(MoveInput != Vector2.zero)
        {
            TurnCheck(MoveInput);

            Vector2 TargetVelocity = Vector2.zero;
            if (playerControls.mainActions.Sprint.ReadValue<bool>())
            {
                TargetVelocity = new Vector2(MoveInput.x, 0f) * ControllStats.MaxRunSpeed;
            }
            else
            {
                TargetVelocity = new Vector2(MoveInput.x, 0f) * ControllStats.MaxWalkSpeed;
            }

            MoveVelocity = Vector2.Lerp(MoveVelocity, TargetVelocity, Acceleration * Time.fixedDeltaTime);
            rb.velocity = new Vector2(MoveVelocity.x, rb.velocity.y);
        }
        else if(MoveInput == Vector2.zero)
        {
            MoveVelocity = Vector2.Lerp(MoveVelocity, Vector2.zero, Deceleration * Time.fixedDeltaTime);
            rb.velocity = new Vector2(MoveVelocity.x, rb.velocity.y);
        }
    }

    private void TurnCheck(Vector2 MoveInput)
    {
        if (!isFacingRight && MoveInput.x < 0)
        {
            Turn(false);
        }
        else if (!isFacingRight && MoveInput.x > 0)
        {
            Turn(true);
        }
    }

    private void Turn(bool TurnRight)
    {
        if(TurnRight)
        {
            isFacingRight = true;
            transform.Rotate(0f, 180f, 0f);
        }
        else
        {
            isFacingRight = false;
            transform.Rotate(0f, -180f, 0f);
        }
    }

    private void Grounded()
    {
        Vector2 BoxCastOrigin = new Vector2(FeetColl.bounds.center.x, FeetColl.bounds.min.y);
        Vector2 BoxCastSize = new Vector2(FeetColl.bounds.size.x, ControllStats.GroundDetectionRayLength);

        GroundHit = Physics2D.BoxCast(BoxCastOrigin, BoxCastSize, 0f, Vector2.down, ControllStats.GroundDetectionRayLength, ControllStats.GroundLayer);
        if (GroundHit.collider != null)
        {
            IsGrounded = true;
        }
        else
        {
            IsGrounded = false;
        }
    }
    private void HasBumpedHead()
    {
        Vector2 BoxCastOrigin = new Vector2(FeetColl.bounds.center.x, BodyColl.bounds.max.y);
        Vector2 BoxCastSize = new Vector2(FeetColl.bounds.size.x * ControllStats.HeadWidth, ControllStats.HeadDetectionRayLength);

        GroundHit = Physics2D.BoxCast(BoxCastOrigin, BoxCastSize, 0f, Vector2.up, ControllStats.HeadDetectionRayLength, ControllStats.GroundLayer);
        if (HeadHit.collider != null)
        {
            BumpedHead = true;
        }
        else
        {
            BumpedHead = false;
        }
    }

    private void CollisionChecks()
    {
        Grounded();
    }
}

Toggle: theme, font