using UnityEngine; namespace Code.Gameplay.Player { public class PlayerController : MonoBehaviour { [SerializeField] private float forwardSpeed = 10f; [SerializeField] private float maxSpeed = 40f; [SerializeField] private float laneDistance = 5f; [SerializeField] private float jumpForce = 11f; [SerializeField] private float gravity = 20f; private int _targetLane = 1; private CharacterController _controller; private Vector3 _direction; public System.Action OnPlayerDeath; private bool _isDead = false; private void Start() { _controller = GetComponent(); } private void Update() { if (_isDead) return; if (UnityEngine.Input.GetKeyDown(KeyCode.RightArrow) || UnityEngine.Input.GetKeyDown(KeyCode.D)) { _targetLane = Mathf.Min(_targetLane + 1, 2); } else if (UnityEngine.Input.GetKeyDown(KeyCode.LeftArrow) || UnityEngine.Input.GetKeyDown(KeyCode.A)) { _targetLane = Mathf.Max(_targetLane - 1, 0); } var targetPosition = transform.position.z * transform.forward + transform.position.y * transform.up; switch (_targetLane) { case 0: targetPosition += Vector3.left * laneDistance; break; case 2: targetPosition += Vector3.right * laneDistance; break; } if (_controller.isGrounded) { _direction.y = -1f; if (UnityEngine.Input.GetKeyDown(KeyCode.Space)) { _direction.y = jumpForce; } } else { _direction.y -= gravity * Time.deltaTime; } _direction.z = forwardSpeed; var diff = targetPosition - transform.position; var moveDir = diff.normalized * (25f * Time.deltaTime); var moveX = Mathf.Clamp(diff.x, -moveDir.magnitude, moveDir.magnitude); var finalMove = new Vector3(moveX, _direction.y * Time.deltaTime, _direction.z * Time.deltaTime); _controller.Move(finalMove); CheckForDeath(); } public void IncreaseSpeed(float amount) { if (forwardSpeed < maxSpeed) { var desirableSpeed = forwardSpeed + amount; forwardSpeed = Mathf.Min(desirableSpeed, maxSpeed); } } private void OnTriggerEnter(Collider foreign) { if (foreign.CompareTag("Coin")) { UI.GameplayController.Instance.AddCoin(); Destroy(foreign.gameObject); } } private void CheckForDeath() { if (_isDead) return; if (Time.timeSinceLevelLoad > 1f && _controller.velocity.z <= 0.1f) { Die(); } } private void Die() { _isDead = true; forwardSpeed = 0; _direction = Vector3.zero; OnPlayerDeath?.Invoke(); } } }