pgiz4/Assets/Scripts/PlayerController.cs

162 lines
4.9 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<Rigidbody>();
animator = GetComponent<Animator>();
capsuleCollider = GetComponent<CapsuleCollider>();
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();
}
}