using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
[Header("Components")]
private Rigidbody2D rb;
private Animator anim;
private SpriteRenderer spriteRend;
[Header("Move Paramaeters")]
[SerializeField] private float maxSpeed = 12f;
[SerializeField] private float moveAcceleration = 50f;
[SerializeField] private float linearDrag = 10f;
private float horizontalInput;
private bool changingDirection => (rb.velocity.x > 0f && horizontalInput < 0f) || (rb.velocity.x < 0f && horizontalInput > 0f);
[Header("Jump Variables")]
[SerializeField] private float jumpForce = 12f;
[SerializeField] private float fallMultiplier = 8f;
[SerializeField] private float lowJumpFallMultiplier = 5f;
[SerializeField] private float airLinearDrag = 2.5f;
[SerializeField] private int extraJumps = 1;
private int extraJumpsValue;
private bool canJump => Input.GetButtonDown("Jump") && (onGround || extraJumpsValue > 0);
[Header("Layer Masks")]
[SerializeField] private LayerMask groundLayer;
[Header("Ground Collision")]
[SerializeField] private float groundRaycastLength;
private bool onGround;
private void Awake()
{
rb = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
spriteRend = GetComponent<SpriteRenderer>();
}
private void Update()
{
horizontalInput = GetInput().x;
if (canJump) Jump();
anim.SetBool("isGrounded", onGround);
anim.SetFloat("horizontalInput", Mathf.Abs(horizontalInput));
if (rb.velocity.y < 0f)
{
anim.SetBool("isJumping", false);
anim.SetBool("isFalling", true);
}
FlipSprite();
}
private void FixedUpdate()
{
CheckCollisions();
MoveCharacter();
if(onGround)
{
extraJumpsValue = extraJumps;
ApplyGroundLinearDrag();
anim.SetBool("isJumping", false);
anim.SetBool("isFalling", false);
}
else
{
ApplyAirLinearDrag();
FallMultipler();
}
}
private Vector2 GetInput()
{
return new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));
}
private void MoveCharacter()
{
rb.AddForce(new Vector2(horizontalInput, 0) * moveAcceleration);
if(Mathf.Abs(rb.velocity.x) > maxSpeed)
{
rb.velocity = new Vector2(Mathf.Sign(rb.velocity.x) * maxSpeed, rb.velocity.y);
}
}
private void ApplyGroundLinearDrag()
{
if (Mathf.Abs(horizontalInput) < 0.4f || changingDirection)
{
rb.drag = linearDrag;
}
else
{
rb.drag = 0f;
}
}
private void ApplyAirLinearDrag()
{
rb.drag = airLinearDrag;
}
private void FallMultipler()
{
if(rb.velocity.y < 0f)
{
rb.gravityScale = fallMultiplier;
}
else if(rb.velocity.y > 0f && !Input.GetButton("Jump"))
{
rb.gravityScale = lowJumpFallMultiplier;
}
else
{
rb.gravityScale = 1f;
}
}
private void Jump()
{
if(!onGround)
{
extraJumpsValue--;
}
anim.SetBool("isJumping", true);
anim.SetBool("isFalling", false);
rb.velocity = new Vector2(rb.velocity.x, 0f);
rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
}
private void CheckCollisions()
{
onGround = Physics2D.Raycast(transform.position, Vector2.down, groundRaycastLength, groundLayer);
}
private void OnDrawGizmos()
{
Gizmos.color = Color.magenta;
Gizmos.DrawLine(transform.position, transform.position + Vector3.down * groundRaycastLength);
}
private void FlipSprite()
{
if(horizontalInput > 0)
{
spriteRend.flipX = false;
}
if(horizontalInput < 0)
{
spriteRend.flipX = true;
}
}
}