using UnityEngine; using System; using System.Collections; [RequireComponent(typeof(Animator), typeof(CapsuleCollider))] public class PlayerController : MonoBehaviour { [Header("Movement")] public float moveSpeed = 8f; public float speedIncreaseRate = 0.1f; public float jumpForce = 10f; public float laneChangeSpeed = 15f; public float laneWidth = 4f; [Header("Gameplay")] public float invincibilityDuration = 5f; // Длительность неуязвимости в секундах [Header("Collider")] public float slideColliderHeight = 0.5f; public float slideColliderCenterY = 0.25f; private Rigidbody rb; private Animator animator; private CapsuleCollider capsuleCollider; private bool isGrounded = true; private bool isSliding = false; private bool isInvincible = false; private int currentLane = 0; private Vector3 targetPosition; private float originalColliderHeight; private float originalColliderCenterY; public static int coinCount = 0; public static event Action OnPlayerDied; private bool isAlive = true; void Start() { rb = GetComponent(); animator = GetComponent(); capsuleCollider = GetComponent(); originalColliderHeight = capsuleCollider.height; originalColliderCenterY = capsuleCollider.center.y; coinCount = 0; isAlive = true; Time.timeScale = 1f; targetPosition = transform.position; } void Update() { if (!isAlive) return; moveSpeed += speedIncreaseRate * Time.deltaTime; HandleInput(); MovePlayer(); } void HandleInput() { if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow)) ChangeLane(-1); else if (Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow)) ChangeLane(1); if (Input.GetKeyDown(KeyCode.Space) && isGrounded) Jump(); if (Input.GetKeyDown(KeyCode.S) || Input.GetKeyDown(KeyCode.DownArrow)) Slide(); } void MovePlayer() { targetPosition.x = currentLane * laneWidth; Vector3 newPosition = new Vector3( Mathf.Lerp(transform.position.x, targetPosition.x, laneChangeSpeed * Time.deltaTime), transform.position.y, transform.position.z + moveSpeed * Time.deltaTime ); transform.position = newPosition; } void ChangeLane(int direction) { int newLane = currentLane + direction; if (newLane >= -1 && newLane <= 1) currentLane = newLane; } void Jump() { isGrounded = false; rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse); animator.SetTrigger("Jump"); } void Slide() { if (!isSliding) { isSliding = true; animator.SetTrigger("Slide"); capsuleCollider.height = slideColliderHeight; capsuleCollider.center = new Vector3(0, slideColliderCenterY, 0); Invoke(nameof(StopSliding), 0.75f); } } void StopSliding() { isSliding = false; capsuleCollider.height = originalColliderHeight; capsuleCollider.center = new Vector3(0, originalColliderCenterY, 0); } void OnCollisionEnter(Collision collision) { if (collision.gameObject.CompareTag("Ground")) isGrounded = true; // Если мы неуязвимы, игнорируем столкновения с препятствиями if (isInvincible) return; if (collision.gameObject.CompareTag("Obstacle") && isAlive) Die(); else if (collision.gameObject.CompareTag("HighObstacle") && !isSliding && isAlive) Die(); } void OnTriggerEnter(Collider other) { if (!isAlive) return; if (other.gameObject.CompareTag("Coin")) { coinCount++; AudioManager.Instance.PlayCoinSound(); Destroy(other.gameObject); } else if (other.gameObject.CompareTag("InvincibilityBonus")) { StartCoroutine(ActivateInvincibility()); Destroy(other.gameObject); } } private IEnumerator ActivateInvincibility() { isInvincible = true; Debug.Log("Неуязвимость активирована!"); // Здесь можно добавить визуальный эффект, например, изменение цвета материала yield return new WaitForSeconds(invincibilityDuration); isInvincible = false; Debug.Log("Неуязвимость закончилась."); } void Die() { isAlive = false; animator.SetBool("IsDead", true); if (OnPlayerDied != null) Invoke(nameof(TriggerGameOver), 1.5f); } void TriggerGameOver() { Time.timeScale = 0f; OnPlayerDied(); } }