Initialisation
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.AI;
|
||||
|
||||
[RequireComponent(typeof(NavMeshAgent))]
|
||||
[RequireComponent(typeof(HealthManager))]
|
||||
public class EnemyAI : MonoBehaviour
|
||||
{
|
||||
private NavMeshAgent agent;
|
||||
private HealthManager health;
|
||||
private Renderer rend;
|
||||
private Transform playerTransform;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
agent = GetComponent<NavMeshAgent>();
|
||||
health = GetComponent<HealthManager>();
|
||||
rend = GetComponent<Renderer>() ?? GetComponentInChildren<Renderer>();
|
||||
health.DeathEvent.AddListener(OnDeath);
|
||||
|
||||
var rb = GetComponent<Rigidbody>();
|
||||
var playerCol = GameObject.FindWithTag("Player").GetComponent<Collider>();
|
||||
var selfCol = GetComponent<Collider>();
|
||||
Physics.IgnoreCollision(playerCol, selfCol);
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
// Ищем игрока по тэгу “Player” (рекомендуется назначить тег в инспекторе)
|
||||
GameObject playerObj = GameObject.FindWithTag("Player");
|
||||
if (playerObj != null)
|
||||
playerTransform = playerObj.transform;
|
||||
|
||||
// Устанавливаем рандомную скорость для NavMeshAgent
|
||||
if (agent != null)
|
||||
{
|
||||
agent.speed = Random.Range(2, 10);
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// Защита от null
|
||||
if (playerTransform == null || agent == null)
|
||||
return;
|
||||
|
||||
// Даем команду агенту идти к игроку
|
||||
agent.SetDestination(playerTransform.position);
|
||||
|
||||
// Обновляем цвет по здоровью (ваша логика)
|
||||
float hpPercent = (float)health.Health / health.MaxHealth;
|
||||
Color c = new Color(1f, 1f - hpPercent, 1f - hpPercent);
|
||||
if (rend != null)
|
||||
rend.material.color = c;
|
||||
}
|
||||
|
||||
private void OnDeath()
|
||||
{
|
||||
if (agent != null)
|
||||
agent.isStopped = true;
|
||||
Destroy(gameObject);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: acfc295074ca4d34a8c8820d36ac0b4c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,35 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class EnemyDamageZone : MonoBehaviour
|
||||
{
|
||||
[Header("Параметры урона")]
|
||||
public int minDamageAmount = 5;
|
||||
public int maxDamageAmount = 30;
|
||||
public float damageCooldown = 1.0f; // Пауза между ударами
|
||||
|
||||
private float lastDamageTime;
|
||||
private int currentDamage;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// При старте задаём случайный урон для этой DamageZone
|
||||
currentDamage = Random.Range(minDamageAmount, maxDamageAmount + 1);
|
||||
}
|
||||
|
||||
private void OnTriggerStay(Collider other)
|
||||
{
|
||||
if (other.CompareTag("Player"))
|
||||
{
|
||||
if (Time.time > lastDamageTime + damageCooldown)
|
||||
{
|
||||
var playerHealth = other.GetComponent<HealthManager>();
|
||||
if (playerHealth != null)
|
||||
{
|
||||
playerHealth.Hit(currentDamage);
|
||||
lastDamageTime = Time.time;
|
||||
Debug.Log("Now HP is: " + playerHealth.Health);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 78a095f023df94abe9877ae699dd321d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,49 @@
|
||||
using System; // Пространство имён .NET с базовыми типами (не используется напрямую, но часто подключается по умолчанию)
|
||||
using UnityEngine; // Основное пространство имён Unity — содержит MonoBehaviour, Mathf и пр.
|
||||
using UnityEngine.Events; // Подключает UnityEvent — систему событий Unity
|
||||
|
||||
public class HealthManager : MonoBehaviour // Класс HealthManager, наследник MonoBehaviour, чтобы его можно было вешать на GameObject
|
||||
{
|
||||
public int MaxHealth; // Публичное поле — максимальное здоровье, задаётся в инспекторе
|
||||
public int Health { // Авто-свойство для чтения текущего здоровья извне, скрывая сеттер
|
||||
get { return health; } // геттер возвращает приватное поле health
|
||||
private set { health = value; } // приватный сеттер позволяет менять health только внутри этого класса
|
||||
}
|
||||
private int health; // Приватное поле, хранящее текущее здоровье
|
||||
|
||||
public UnityEvent DeathEvent; // Событие без параметров, вызывается при смерти
|
||||
public UnityEvent<int> ChangeEvent; // Событие с параметром int, передаёт величину изменения здоровья
|
||||
|
||||
private void Awake() // Awake вызывается одним из первых — при создании объекта
|
||||
{
|
||||
health = MaxHealth; // Инициализируем текущее здоровье максимальным
|
||||
}
|
||||
|
||||
private void HandleHealth() // Вспомогательный метод для проверки границ и обработки смерти
|
||||
{
|
||||
Health = Mathf.Min(MaxHealth, Health); // Если health > MaxHealth, обрезаем до MaxHealth
|
||||
Health = Mathf.Max(0, Health); // Если health < 0, обрезаем до 0
|
||||
|
||||
if (Health == 0) // Если текущее здоровье упало до нуля
|
||||
Die(); // вызываем метод Die для обработки смерти
|
||||
}
|
||||
|
||||
public void Die() // Метод «смерти»
|
||||
{
|
||||
DeathEvent.Invoke(); // Вызываем все слушатели события DeathEvent
|
||||
}
|
||||
|
||||
public void Hit(int amount) // Метод нанесения урона
|
||||
{
|
||||
Health -= amount; // Уменьшаем текущие очки здоровья на amount
|
||||
HandleHealth(); // Корректируем границы и проверяем смерть
|
||||
ChangeEvent.Invoke(amount); // Уведомляем всех подписчиков о величине изменения (передаём отрицательное число)
|
||||
}
|
||||
|
||||
public void heal(int amount) // Метод лечения
|
||||
{
|
||||
Health += amount; // Увеличиваем текущее здоровье на amount
|
||||
HandleHealth(); // Корректируем границы и проверяем смерть (на случай, если health превысило MaxHealth)
|
||||
ChangeEvent.Invoke(amount); // Уведомляем всех подписчиков о величине изменения (передаём положительное число)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a47499a0abd59464bb5eba58245d22df
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class HelloWorld : MonoBehaviour
|
||||
{
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
Debug.Log("Hello, world!");
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d8a003818908298489652540eb137b7a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,64 @@
|
||||
using System.Collections; // Подключает пространство имён для базовых коллекций Unity (не используется напрямую, но часто включается по умолчанию)
|
||||
using System.Collections.Generic; // Подключает пространство имён для обобщённых коллекций (List, Dictionary и т.д.)
|
||||
using UnityEngine; // Основное пространство имён Unity — всё, что связано с движком и игровыми объектами
|
||||
|
||||
public class LaserGun : MonoBehaviour // Объявление класса LaserGun, наследующегося от MonoBehaviour — базового класса всех компонентов Unity
|
||||
{
|
||||
//private LineRenderer laserLine; // Закомментированное поле для LineRenderer (если бы вы рисовали лазер линией)
|
||||
|
||||
public GameObject laserObject; // Ссылка на объект-луч (например, цилиндр или спрайт), который будет включаться/выключаться
|
||||
public float laserDuration = 1f; // Время (в секундах), в течение которого лазер остаётся активным (используется, если рисовать корутиной)
|
||||
public Transform laserOrigin; // Точка (Transform) в пространстве, откуда исходит лазер
|
||||
public Camera playerCamera; // Камера игрока — нужна, чтобы определить направление выстрела
|
||||
public float laserRange = 50f; // Максимальная дальность луча
|
||||
|
||||
public LayerMask layermask;
|
||||
|
||||
void Start() // Метод Start вызывается один раз при активации компонента (перед первым Update)
|
||||
{
|
||||
//laserLine = GetComponent<LineRenderer>(); // Если бы вы использовали LineRenderer, тут получили бы его из текущего объекта
|
||||
}
|
||||
void Update()
|
||||
{
|
||||
if (Input.GetButton("Fire1"))
|
||||
{
|
||||
Vector3 rayOrigin = playerCamera.ViewportToWorldPoint(new Vector2(0.5f, 0.5f));
|
||||
Ray ray = new Ray(rayOrigin, playerCamera.transform.forward);
|
||||
RaycastHit hit;
|
||||
|
||||
Vector3 rayEnd;
|
||||
Vector3 rayStart = laserOrigin.position;
|
||||
|
||||
if (Physics.Raycast(ray, out hit, laserRange, layermask))
|
||||
{
|
||||
rayEnd = hit.point;
|
||||
|
||||
// Ищем HealthManager только на первом попавшемся объекте
|
||||
HealthManager health = hit.transform.GetComponent<HealthManager>();
|
||||
if (health != null && hit.transform.gameObject.tag != "Player")
|
||||
{
|
||||
health.Die(); // Убиваем врага
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rayEnd = rayOrigin + playerCamera.transform.forward * laserRange;
|
||||
}
|
||||
|
||||
Vector3 laserVec = (rayEnd - rayStart);
|
||||
float laserLength = laserVec.magnitude * 0.5f;
|
||||
Vector3 laserDirection = (rayEnd - rayStart).normalized;
|
||||
|
||||
laserObject.transform.position = rayStart;
|
||||
laserObject.transform.localScale = new Vector3(0.2f, laserLength, 0.2f);
|
||||
laserObject.transform.rotation = transform.rotation;
|
||||
|
||||
laserObject.SetActive(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
laserObject.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eeac6cf62316e154e8041833aa8ddb8b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,100 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using System.Collections;
|
||||
|
||||
[RequireComponent(typeof(Image))]
|
||||
public class BarClickHighlighter : MonoBehaviour
|
||||
{
|
||||
[Header("Настройки кликов")]
|
||||
[Tooltip("Сколько раз нужно кликнуть ПКМ, чтобы поменять цвет")]
|
||||
public int clicksThreshold = 6;
|
||||
|
||||
[Header("Цвет")]
|
||||
[Tooltip("Новый цвет после достижения порога")]
|
||||
public Color highlightColor = new Color32(0xD5, 0x31, 0x31, 0xFF);
|
||||
|
||||
[Header("Опции сброса")]
|
||||
[Tooltip("Сбрасывать счётчик после смены цвета?")]
|
||||
public bool resetAfterHighlight = true;
|
||||
|
||||
[Header("Здоровье игрока при перегреве")]
|
||||
public HealthManager playerHealth;
|
||||
public int overheatDamage = 10;
|
||||
public float damageInterval = 2f;
|
||||
|
||||
private int clickCount = 0;
|
||||
private Image barImage;
|
||||
private Color originalColor;
|
||||
private bool isOverheated = false;
|
||||
private Coroutine overheatDamageCoroutine;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
barImage = GetComponent<Image>();
|
||||
originalColor = barImage.color;
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
if (Input.GetButtonDown("Fire1"))
|
||||
{
|
||||
clickCount++;
|
||||
|
||||
if (clickCount >= clicksThreshold && !isOverheated)
|
||||
{
|
||||
Debug.Log("Threshold reached — changing color!");
|
||||
HighlightBar();
|
||||
StartOverheatDamage();
|
||||
|
||||
if (resetAfterHighlight)
|
||||
clickCount = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HighlightBar()
|
||||
{
|
||||
barImage.color = highlightColor;
|
||||
}
|
||||
|
||||
private IEnumerator ResetColorAfterSeconds(float sec)
|
||||
{
|
||||
yield return new WaitForSeconds(sec);
|
||||
barImage.color = originalColor;
|
||||
}
|
||||
|
||||
private void StartOverheatDamage()
|
||||
{
|
||||
isOverheated = true;
|
||||
overheatDamageCoroutine = StartCoroutine(OverheatDamageCoroutine());
|
||||
}
|
||||
|
||||
private IEnumerator OverheatDamageCoroutine()
|
||||
{
|
||||
while (isOverheated)
|
||||
{
|
||||
if (playerHealth != null)
|
||||
{
|
||||
playerHealth.Hit(overheatDamage);
|
||||
}
|
||||
yield return new WaitForSeconds(damageInterval);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetOverheat()
|
||||
{
|
||||
clickCount = 0;
|
||||
isOverheated = false;
|
||||
|
||||
if (overheatDamageCoroutine != null)
|
||||
{
|
||||
StopCoroutine(overheatDamageCoroutine);
|
||||
overheatDamageCoroutine = null;
|
||||
}
|
||||
|
||||
if (barImage != null)
|
||||
{
|
||||
barImage.color = originalColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a856d4d92448044328b28b0f1315a165
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,67 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayerController : MonoBehaviour
|
||||
{
|
||||
public HealthManager health;
|
||||
private CharacterController cc;
|
||||
private Rigidbody rb;
|
||||
|
||||
public Transform cameraTransform;
|
||||
|
||||
public float sensitivity = 100.0f;
|
||||
public float walkSpeed = 8.0f;
|
||||
public float sprintSpeed = 16.0f;
|
||||
public float gravity = 1f;
|
||||
|
||||
void Start()
|
||||
{
|
||||
health = GetComponent<HealthManager>();
|
||||
if (health != null)
|
||||
health.DeathEvent.AddListener(OnDeath);
|
||||
|
||||
cc = GetComponent<CharacterController>();
|
||||
rb = GetComponent<Rigidbody>();
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
// lock the cursor
|
||||
Cursor.lockState = CursorLockMode.Locked;
|
||||
|
||||
// rotate the camera
|
||||
Vector3 rotation = new Vector3(-Input.GetAxis("Mouse Y"), Input.GetAxis("Mouse X"), 0);
|
||||
rotation *= sensitivity;
|
||||
|
||||
//cameraTransform.eulerAngles += rotation * Time.deltaTime;
|
||||
|
||||
transform.eulerAngles = new Vector3(transform.eulerAngles.x, transform.eulerAngles.y + rotation.y * Time.deltaTime, 0);
|
||||
cameraTransform.eulerAngles = new Vector3(cameraTransform.eulerAngles.x + rotation.x * Time.deltaTime, transform.eulerAngles.y, 0);
|
||||
|
||||
// get rid of the z tilt
|
||||
//cameraTransform.eulerAngles = new Vector3(cameraTransform.eulerAngles.x, 0, 0);
|
||||
|
||||
|
||||
// walking/sprinting logic
|
||||
float moveSpeed = Input.GetKey(KeyCode.LeftShift) ? sprintSpeed : walkSpeed;
|
||||
Vector3 movement = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"))/*.normalized*/ * moveSpeed;
|
||||
|
||||
// make it relative to the camera rotation
|
||||
movement = Quaternion.Euler(0, cameraTransform.eulerAngles.y, 0) * movement;
|
||||
|
||||
// apply the speed
|
||||
//transform.position += movement * Time.deltaTime;
|
||||
cc.Move(movement * Time.deltaTime);
|
||||
|
||||
cc.Move(new Vector3(0f, -gravity * Time.deltaTime, 0f));
|
||||
}
|
||||
|
||||
public void OnDeath()
|
||||
{
|
||||
Debug.Log("player died");
|
||||
Destroy(gameObject); // уничтожить игрока
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 95c9e3e49d0d42e41a689ce8b7ebc9a6
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,38 @@
|
||||
using UnityEngine;
|
||||
|
||||
public class PlayerOverheatReset : MonoBehaviour
|
||||
{
|
||||
public BarClickHighlighter overheatScript;
|
||||
public HealthManager healthManager;
|
||||
public int healAmount = 20;
|
||||
public float healCooldown = 5f; // Кулдаун между лечениями (в секундах)
|
||||
|
||||
private float lastHealTime = -Mathf.Infinity;
|
||||
|
||||
private void OnTriggerEnter(Collider other)
|
||||
{
|
||||
if (other.CompareTag("Platform"))
|
||||
{
|
||||
if (Time.time >= lastHealTime + healCooldown)
|
||||
{
|
||||
Debug.Log("ON A PLATFORM — Healed!");
|
||||
|
||||
if (overheatScript != null)
|
||||
{
|
||||
overheatScript.ResetOverheat();
|
||||
}
|
||||
|
||||
if (healthManager != null)
|
||||
{
|
||||
healthManager.heal(healAmount);
|
||||
}
|
||||
|
||||
lastHealTime = Time.time; // Обновляем момент последнего лечения
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Platform on cooldown...");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5ca890c0824114cfc9f46a278ac9047d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class RotationComplex : MonoBehaviour
|
||||
{
|
||||
public Transform origin;
|
||||
public float radius = 1.0f;
|
||||
public float rotateInterval = 10f;
|
||||
public float tShift = 0.0f;
|
||||
|
||||
public float wave = 0.3f;
|
||||
public float waveInterval = 2f;
|
||||
|
||||
private float rotation;
|
||||
private float t = 0f;
|
||||
private float waveY;
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
t = tShift;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
rotation = (t / rotateInterval) * 360f;
|
||||
waveY = Mathf.Sin(t / waveInterval) * wave;
|
||||
|
||||
transform.position = origin.position + Quaternion.Euler(0f, rotation, 0f) * (origin.forward * radius) + new Vector3(0f, waveY, 0f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf153d96f04d9fd4c88cf83f44440974
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class RotationSimple : MonoBehaviour
|
||||
{
|
||||
public float interval = 10f;
|
||||
private float t;
|
||||
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
t = 0f;
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
t += Time.deltaTime;
|
||||
float rotation = t / interval * 360f;
|
||||
transform.rotation = Quaternion.Euler(0f, rotation, 0f);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3a3b4d781303c248916ee87f09485dc
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
using System.Collections;
|
||||
|
||||
public class HealthUI : MonoBehaviour
|
||||
{
|
||||
public HealthManager playerHealth;
|
||||
public Image healthFill;
|
||||
public TextMeshProUGUI healthText;
|
||||
|
||||
private Coroutine textAnimationCoroutine;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (playerHealth != null)
|
||||
playerHealth.ChangeEvent.AddListener(OnHealthChanged);
|
||||
|
||||
UpdateHealthBarImmediate();
|
||||
}
|
||||
|
||||
private void OnHealthChanged(int amount)
|
||||
{
|
||||
UpdateHealthBarAnimated();
|
||||
}
|
||||
|
||||
private void UpdateHealthBarImmediate()
|
||||
{
|
||||
if (healthFill != null && playerHealth != null)
|
||||
{
|
||||
healthFill.fillAmount = (float)playerHealth.Health / playerHealth.MaxHealth;
|
||||
}
|
||||
|
||||
if (healthText != null && playerHealth != null)
|
||||
{
|
||||
healthText.text = $"{playerHealth.Health} / {playerHealth.MaxHealth}";
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateHealthBarAnimated()
|
||||
{
|
||||
if (healthFill != null && playerHealth != null)
|
||||
{
|
||||
healthFill.fillAmount = (float)playerHealth.Health / playerHealth.MaxHealth;
|
||||
}
|
||||
|
||||
if (healthText != null && playerHealth != null)
|
||||
{
|
||||
if (textAnimationCoroutine != null)
|
||||
StopCoroutine(textAnimationCoroutine);
|
||||
|
||||
textAnimationCoroutine = StartCoroutine(AnimateHealthText());
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerator AnimateHealthText()
|
||||
{
|
||||
int displayedHealth = int.Parse(healthText.text.Split('/')[0].Trim()); // Текущее число на экране
|
||||
int targetHealth = playerHealth.Health; // Реальное здоровье
|
||||
|
||||
float duration = 0.3f; // длительность анимации
|
||||
float elapsed = 0f;
|
||||
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
float t = Mathf.Clamp01(elapsed / duration);
|
||||
int currentHealth = Mathf.RoundToInt(Mathf.Lerp(displayedHealth, targetHealth, t));
|
||||
healthText.text = $"{currentHealth} / {playerHealth.MaxHealth}";
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// в конце выставляем точно правильное значение
|
||||
healthText.text = $"{playerHealth.Health} / {playerHealth.MaxHealth}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c38558547fca04997b2d9ee53feb01e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user