forked from vladislove/pgiz4
162 lines
4.9 KiB
C#
162 lines
4.9 KiB
C#
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();
|
||
}
|
||
}
|