using UnityEngine;
using UnityEngine.InputSystem;
public class PlatformMovement : MonoBehaviour
{
[Header("Input Reference")]
[SerializeField]
private InputActionReference moveAction;
[SerializeField]
private InputActionReference jumpAction;
[Header("Walk Settings")]
[SerializeField]
private float walkSpeed = 5;
[SerializeField]
private float acceleration = 10f;
[SerializeField]
private float deceleration = 20f;
[Header("Jump Settings")]
[SerializeField]
private float jumpHeight = 2.5f;
[SerializeField]
private LayerMask groundLayer;
[SerializeField]
private float inAirControl = 0.3f;
[SerializeField]
private float jumpCancelDivider = 2f;
[SerializeField]
private float coyoteTime = 0.3f;
[Header("Wall Slide Settings")]
[SerializeField]
private float defaultMaxFallSpeed = 30f;
[SerializeField]
private float wallSlideVelocity = 1f;
private bool _isWallSliding;
[Header("Wall Jump Settings")]
[SerializeField]
private bool wallJumpEnabled = true;
private bool _isTouchingWall;
private Vector2 _moveInput;
private Rigidbody2D _rigidbody2D;
private Collider2D _collider2D;
private bool _isGrounded;
private float _coyoteTimer;
private bool _coyoteTimePassed;
private void Awake()
{
_rigidbody2D = GetComponent<Rigidbody2D>();
_collider2D = GetComponent<Collider2D>();
}
private void OnEnable()
{
moveAction.action.performed += HandleWalkInput;
moveAction.action.canceled += HandleWalkInput;
jumpAction.action.performed += HandleJumpInput;
jumpAction.action.canceled += HandleJumpInput;
jumpAction.action.canceled += HandleJumpCancelled;
}
private void OnDisable()
{
moveAction.action.performed -= HandleWalkInput;
moveAction.action.canceled -= HandleWalkInput;
jumpAction.action.performed -= HandleJumpInput;
jumpAction.action.canceled -= HandleJumpInput;
jumpAction.action.canceled -= HandleJumpCancelled;
}
private void Update()
{
_isTouchingWall = WallCheck();
_isGrounded = GroundCheck();
HandleWalking();
HandleWallSlide();
UpdateCoyoteTime();
if (_isGrounded && _rigidbody2D.linearVelocity.y <= 0)
{
ResetCoyoteTime();
}
}
private void HandleWalkInput(InputAction.CallbackContext context)
{
_moveInput = context.ReadValue<Vector2>();
}
private void HandleJumpInput(InputAction.CallbackContext context)
{
if (_isTouchingWall && !_isGrounded && _isWallSliding)
{
wallJumpEnabled = true;
}
else
{
wallJumpEnabled = false;
}
if (!_coyoteTimePassed || (wallJumpEnabled && _isTouchingWall))
{
HandleJumping();
}
}
private void HandleJumpCancelled(InputAction.CallbackContext context)
{
if (_rigidbody2D.linearVelocity.y > 0)
{
_rigidbody2D.linearVelocity.y /= jumpCancelDivider;
}
}
private void HandleWalking()
{
var control = _isGrounded ? 1 : inAirControl;
var change = _moveInput.x != 0 ? acceleration : deceleration;
_rigidbody2D.linearVelocity.x = Mathf.Lerp(_rigidbody2D.linearVelocity.x, _moveInput.x * walkSpeed, Time.deltaTime * change * control);
}
private void HandleJumping()
{
var actualGravity = Mathf.Abs(Physics2D.gravity.y) * _rigidbody2D.gravityScale;
_rigidbody2D.linearVelocity.y = Mathf.Sqrt(2 * jumpHeight * actualGravity);
}
private void HandleWallSlide()
{
if (_isTouchingWall && _rigidbody2D.linearVelocity.y < 0)
{
_rigidbody2D.linearVelocity.y = Mathf.Max(_rigidbody2D.linearVelocity.y, -wallSlideVelocity);
_isWallSliding = true;
}
else
{
_isWallSliding = false;
}
}
private bool GroundCheck()
{
var colliderBottomCenter = new Vector2(_collider2D.bounds.center.x, _collider2D.bounds.min.y);
return Physics2D.OverlapBox(colliderBottomCenter, new Vector2(_collider2D.bounds.size.x - 0.1f, 0.1f), 0, groundLayer);
}
private bool WallCheck()
{
float rayDistance = _collider2D.bounds.extents.x + 0.05f;
Vector2 origin = _collider2D.bounds.center;
RaycastHit2D hitRight = Physics2D.Raycast(origin, Vector2.right, rayDistance, groundLayer);
RaycastHit2D hitLeft = Physics2D.Raycast(origin, Vector2.left, rayDistance, groundLayer);
return hitLeft || hitRight;
}
private void UpdateCoyoteTime()
{
if (!_isGrounded && !_coyoteTimePassed)
{
_coyoteTimer += Time.deltaTime;
}
}
private void ResetCoyoteTime()
{
_coyoteTimer = 0;
}
private void Start()
{
_coyoteTimePassed = false;
}
}
评论 (0)