using UnityEngine; using Code.Input; namespace Code.Gameplay.Player { public class PlayerMovement : MonoBehaviour { [SerializeField] private Rigidbody2D _rb; [SerializeField] private Transform _groundCheck; [SerializeField] private LayerMask _groundLayer; [SerializeField] private Animator _animator; [SerializeField] private float _moveSpeed = 5f; [SerializeField] private float _sprintSpeedMultiplier = 1.8f; [SerializeField] private float _jumpForce = 12f; [SerializeField] private float _groundCheckRadius = 0.2f; [SerializeField] private float _jumpDuration = 0.5f; private IInputService _input; private bool _isJumping; private float _jumpTimer; private RuntimeAnimatorController _idleAnimator; private RuntimeAnimatorController _walkAnimator; private RuntimeAnimatorController _jumpAnimator; public bool isGrounded { get; private set; } public void Construct(IInputService input) { _input = input; _animator.runtimeAnimatorController = null; _idleAnimator = Resources.Load("Animations/penguin_idle_01"); _walkAnimator = Resources.Load("Animations/penguin_walk_01"); _jumpAnimator = Resources.Load("Animations/penguin_jump_01"); } private void Update() { CheckGround(); HandleInput(); } private void FixedUpdate() { Move(); HandleJump(); } private void HandleInput() { switch (_input.JumpPressed) { case true when isGrounded: _isJumping = true; _jumpTimer = 0f; _rb.linearVelocity = new Vector2(_rb.linearVelocity.x, _jumpForce); break; case false when _isJumping: { _isJumping = false; if (_rb.linearVelocity.y > 0) _rb.linearVelocity = new Vector2(_rb.linearVelocity.x, _rb.linearVelocity.y * 0.5f); break; } } UpdateFacingDirection(); UpdateAnimations(); } private void UpdateFacingDirection() { transform.rotation = _input.MoveInput switch { > 0 => Quaternion.identity, < 0 => Quaternion.Euler(0, -180, 0), _ => transform.rotation }; } private void UpdateAnimations() { var isMoving = Mathf.Abs(_input.MoveInput) > 0.1f; var isJumping = !isGrounded; if (isJumping) { if (_animator.runtimeAnimatorController != _jumpAnimator) _animator.runtimeAnimatorController = _jumpAnimator; } else if (isMoving) { if (_animator.runtimeAnimatorController != _walkAnimator) _animator.runtimeAnimatorController = _walkAnimator; } else if (_animator.runtimeAnimatorController != _idleAnimator) _animator.runtimeAnimatorController = _idleAnimator; } private void CheckGround() { isGrounded = Physics2D.OverlapCircle(_groundCheck.position, _groundCheckRadius, _groundLayer); } private void Move() { var moveInput = _input.MoveInput; var speed = _input.SprintHeld ? _moveSpeed * _sprintSpeedMultiplier : _moveSpeed; var targetVelocityX = moveInput * speed; _rb.linearVelocity = new Vector2(targetVelocityX, _rb.linearVelocity.y); } private void HandleJump() { if (!_isJumping || !_input.JumpPressed) return; _jumpTimer += Time.fixedDeltaTime; if (!(_jumpTimer < _jumpDuration && _rb.linearVelocity.y > 0)) { _isJumping = false; } } private void OnDrawGizmosSelected() { if (_groundCheck == null) return; Gizmos.color = isGrounded ? Color.green : Color.red; Gizmos.DrawWireSphere(_groundCheck.position, _groundCheckRadius); } } }