Как сделать полоску здоровья (health bar) в Unity3D

Появившаяся ещё в ранних видеоиграх механика здоровья остаётся ключевой в современных проектах. Полоска здоровья упрощает восприятие боя, позволяет строить прогрессию героя и делает механику явной для игрока. Unity3D упрощает добавление 2D UI в 3D-сцены, поэтому это отличная платформа для реализации полоски здоровья.
Что вы узнаете
На первый взгляд задача простая, но для корректной реализации вам понадобятся знания о следующих вещах:
- Создание 2D UI-элементов и спрайтов в Unity3D.
- Редактирование компонентов GameObject через код.
- Передача и чтение переменных между скриптами в Unity.
Шаг 1: Подготовьте сцену и UI
Перед кодированием вам нужна сцена с игровым персонажем. Если у вас ещё нет контроллера персонажа, можно начать с простого физического контроллера и базовых входов (WASD).
- Откройте окно Hierarchy, щёлкните правой кнопкой и выберите UI > Image. Unity создаст Canvas и дочерний Image. Переименуйте дочерний объект в Healthbar. Выберите ширину, высоту и позицию через Inspector.
Добавьте чуть больший Image под полоской как фон или рамку. Поместите фон выше (в иерархии) так, чтобы он отображался за самой полоской.
Создайте спрайт: в Project pane правой кнопкой Create > 2D > Sprites > Square. Перетащите спрайт в поле Source Image у компонента Image выбранного Healthbar.
В Inspector измените Image Type на Filled, Fill Method на Horizontal, Fill Origin на Left. При запуске сцены ползунок Fill Amount будет физически менять ширину полоски.
- Если не видите 2D-пакета, откройте Window > Package Manager и установите необходимые пакеты.
Важно: сохраняйте размеры и якоря (anchors) UI-элемента в зависимости от разрешения экрана, чтобы полоска адекватно масштабировалась.
Шаг 2: Добавьте переменную здоровья в контроллер персонажа
Переменная здоровья должна быть доступна другим скриптам. Добавьте её в ваш скрипт управления персонажем (например, Character_Control) как public float:
// В Character_Control.cs
public float playerHealth = 1.0f; // 1.0f = 100% здоровья, 0.0f = 0%Использование float удобно, потому что Fill Amount у Image тоже представляет собой float от 0 до 1.
Шаг 3: Чтение переменной из другого скрипта
Создайте новый скрипт Health.cs и прикрепите его к объекту Healthbar. В методе Update нужно найти объект персонажа, получить его компонент и прочитать playerHealth.
Пример корректного и работоспособного кода:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Health : MonoBehaviour
{
private static Image Healthbar;
public float currentHealth;
void Start()
{
Healthbar = GetComponent();
}
void Update()
{
GameObject Character_Model = GameObject.Find("Character_Model");
if (Character_Model != null)
{
Character_Control character_Control = Character_Model.GetComponent();
if (character_Control != null)
{
currentHealth = character_Control.playerHealth;
Healthbar.fillAmount = currentHealth;
}
else
{
// Можно логировать ошибку: компонент не найден
}
}
else
{
// Можно логировать ошибку: объект персонажа не найден
}
}
} Обратите внимание: GetComponent
Шаг 4: Изменение цвета в зависимости от состояния
Чтобы полосу менять по цвету, добавьте логику выбора цвета:
Color greenHealth = new Color(0.6f, 1f, 0.6f, 1f);
if (currentHealth >= 0.3f)
{
Healthbar.color = greenHealth;
}
else
{
Healthbar.color = Color.red;
}Можно расширить пороги и использовать градиентные переходы или плавное изменение цвета через Lerp.
Полный пример скрипта Health (интегрированный)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Health : MonoBehaviour
{
private static Image Healthbar;
public float currentHealth;
void Start()
{
Healthbar = GetComponent();
}
void Update()
{
GameObject Character_Model = GameObject.Find("Character_Model");
if (Character_Model == null) return;
Character_Control character_Control = Character_Model.GetComponent();
if (character_Control == null) return;
currentHealth = Mathf.Clamp01(character_Control.playerHealth);
Healthbar.fillAmount = currentHealth;
Color greenHealth = new Color(0.6f, 1f, 0.6f, 1f);
if (currentHealth >= 0.3f)
{
Healthbar.color = greenHealth;
}
else
{
Healthbar.color = Color.red;
}
}
} Важная деталь: использована Mathf.Clamp01, чтобы гарантировать, что fillAmount всегда будет в диапазоне 0–1.
Шаг 5: Простейший способ тестирования
Чтобы видеть изменение полоски во время игры, временно уменьшайте игроку здоровье при нажатии клавиш. Пример — в Character_Control добавить:
// Внутри метода Update контроллера
if (Input.GetKey(KeyCode.W))
{
playerHealth -= 0.001f; // медленное снижение при удержании W
playerHealth = Mathf.Clamp01(playerHealth);
}Не забывайте возвращать тестовый код в исходное состояние или оборачивать его в #if UNITY_EDITOR, чтобы не оставлять «искусственное» поведение в релизе.
Когда это не сработает — типичные ограничения
- Если вы используете сетевой мультиплеер, чтение состояния напрямую через GameObject.Find на клиенте может привести к рассинхронизации. В сетевых проектах синхронизация должна идти через сервер/реплики.
- Если у вас много персонажей (например, 100+), постоянный вызов GameObject.Find в Update потребляет ресурсы. В таких случаях кешируйте ссылки (например, при создании сущности) или используйте событие/подписку.
- Canvas в режиме Screen Space — Overlay накладывается поверх всего; если вы хотите полоску над конкретным персонажем в мире, используйте World Space Canvas или конвертируйте мировые координаты в экранные.
Альтернативные подходы
- HUD как отдельный контроллер: хранить все UI-ссылки в одном Manager, который подписывается на события изменения здоровья.
- Использовать ScriptableObject для хранения состояния здоровья (полезно для редактора и балансировки).
- Использовать Animator и анимации для плавного уменьшения/увеличения полоски и цветовых переходов.
- Для world-space индикаторов — закреплять Canvas к объекту и поворачивать его к камере (billboard).
Шпаргалка: быстрый чек-лист интеграции
- Создан Canvas и Image для Healthbar.
- Создан фон / рамка для визуала.
- Создан спрайт Square и назначен как Source Image.
- Image Type = Filled, Fill Method = Horizontal, Fill Origin = Left.
- В Character_Control объявлен public float playerHealth.
- Скрипт Health получает ссылку на Image через GetComponent
(). - Health читает playerHealth и присваивает Healthbar.fillAmount.
- Применены проверки на null и Clamp01.
- Тестовое снижение/увеличение здоровья работает.
Мини-методология внедрения
- Спроектируйте требование: HUD на экране или World-space над персонажем.
- Создайте UI и спрайты.
- Объявите модель состояния (переменная здоровья в контроллере или SO).
- Реализуйте связывание через события или прямое чтение.
- Тестируйте на разных разрешениях.
- Оптимизируйте для большого числа сущностей.
Критерии приёмки
- При playerHealth = 1.0 полоса полностью заполнена и зелёная.
- При playerHealth = 0.0 полоса пуста и красная.
- Изменение playerHealth плавно отражается в UI без рывков (при необходимости).
- Для world-space индикатора позиционирование корректно для всех камер.
Тест-кейсы и приёмочные сценарии
- Нормальный сценарий: playerHealth уменьшается от 1 до 0, полоска плавно уменьшается.
- Граничные значения: playerHealth = -0.5 → clamp -> 0; playerHealth = 2.0 → clamp -> 1.
- Отсутствует Character_Model в сцене → Health не падает с ошибкой (обработка null).
- Много сущностей: замерить CPU при 100+ Health объектов без кеширования ссылок.
Производительность и лучшие практики
- Избегайте GameObject.Find в каждом Update. Лучше искать один раз в Start() или кешировать ссылку при создании персонажа.
- Для множества UI-элементов используйте пул объектов и обновления по событиям, а не каждое Update.
- Для динамического отображения (гладкие переходы) используйте корутины или Tween- библиотеки (DOTween и др.).
Резюме
Полоска здоровья — базовый, но критический элемент игрового интерфейса. Правильная архитектура делает код надёжным и масштабируемым: храните состояние в одном месте, кэшируйте ссылки и используйте события для обновления UI, когда это возможно. Этот гайд дал рабочую реализацию, варианты улучшений и подходы для различных сценариев.
Факт-бокс:
- Формат хранения: float 0–1 (процент).
- Ключевой метод: GetComponent
() для получения UI Image. - Рекомендуемая проверка: Mathf.Clamp01(playerHealth).
Короткая аннотация для соцсетей: Простой и надёжный способ добавить полоску здоровья в Unity3D: UI‑Image с Fill, чтение playerHealth из контроллера, корректная типизация и базовые проверки.
Если нужно, могу добавить вариант решения для мультиплеера, world-space индикатор с поворотом к камере или пример с использованием событийнoй системы и ScriptableObject.
Похожие материалы
RDP: полный гид по настройке и безопасности
Android как клавиатура и трекпад для Windows
Советы и приёмы для работы с PDF
Calibration в Lightroom Classic: как и когда использовать
Отключить Siri Suggestions на iPhone