Unity 2d Platformer PlayerController

• Has Movement • Has Coyote Time • Has Time Buffer
mail@pastecode.io avatar
unknown
plain_text
2 months ago
3.8 kB
5
Indexable
Never
using System.Collections;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [SerializeField] private Rigidbody2D rb;

    [Header("Character Movement")]
    [SerializeField] private float speed = 8f;
    [SerializeField] private float deceleration = 30f;
    private float horizontal;
    [SerializeField] private bool isFacingRight = true;

    [Header("Jumping")]
    [SerializeField] private float jumpingPower = 21f;
    private float holdJumpTime;
    private bool isJumping;

    [Header("Jumping Cooldown")]
    [SerializeField] private float coyoteTime = 0.4f;
    private float coyoteTimeCounter;

    [Header("Jump Buffer")]
    [SerializeField] private float jumpBufferTime = 0.2f;
    private float jumpBufferCounter;

    [Header("Ground Check")]
    [SerializeField] private Transform groundCheck;
    [SerializeField] private LayerMask groundLayer;
    [SerializeField] public float groundCheckRadius;

    private void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
        if (rb == null)
        {
            Debug.LogError("Rigidbody2D component not found on the player!");
        }
    }

    private void Update()
    {
        horizontal = Input.GetAxisRaw("Horizontal");

        if (IsGrounded())
        {
            coyoteTimeCounter = coyoteTime;
        }
        else
        {
            coyoteTimeCounter -= Time.deltaTime;
        }

        if (Input.GetButtonDown("Jump"))
        {
            jumpBufferCounter = jumpBufferTime;
        }
        else
        {
            jumpBufferCounter -= Time.deltaTime;
        }

        if (coyoteTimeCounter > 0f && jumpBufferCounter > 0f && !isJumping)
        {
            rb.velocity = new Vector2(rb.velocity.x, jumpingPower);

            jumpBufferCounter = 0f;

            StartCoroutine(JumpCooldown());
        }

        if (Input.GetButtonUp("Jump") && rb.velocity.y > 0f)
        {
            rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * 0.5f);

            coyoteTimeCounter = 0f;
        }

        Flip();
    }

    private void FixedUpdate()
    {
        float horizontalInput = Input.GetAxisRaw("Horizontal");
        float newVelocityX = horizontalInput * speed;

        // Apply deceleration if no movement input
        if (horizontalInput == 0 && Mathf.Abs(rb.velocity.x) > 0)
        {
            // Calculate the direction of the current velocity
            float decelerationDirection = Mathf.Sign(rb.velocity.x);

            // Calculate the new velocity after applying deceleration
            newVelocityX = rb.velocity.x - deceleration * decelerationDirection * Time.fixedDeltaTime;

            // Ensure velocity doesn't overshoot zero due to deceleration
            if (Mathf.Sign(newVelocityX) != decelerationDirection)
            {
                newVelocityX = 0f;
            }
        }

        rb.velocity = new Vector2(newVelocityX, rb.velocity.y);
    }


    private bool IsGrounded()
    {
        return Physics2D.OverlapCircle(groundCheck.position, 0.2f, groundLayer);
    }

    private void Flip()
    {
        if (isFacingRight && horizontal < 0f || !isFacingRight && horizontal > 0f)
        {
            Vector3 localScale = transform.localScale;
            isFacingRight = !isFacingRight;
            localScale.x *= -1f;
            transform.localScale = localScale;
        }
    }

    private IEnumerator JumpCooldown()
    {
        isJumping = true;
        yield return new WaitForSeconds(0.4f);
        isJumping = false;
    }
    private void OnDrawGizmos()
    {
        Gizmos.DrawWireSphere(groundCheck.position, groundCheckRadius);
    }
}
Leave a Comment