Когда нужен Entity, а когда обычный класс
Не добавляйте объект в иерархию, если ему нужны только данные и вычисления.
Выбор по обязанностям
| Нужна возможность | Что использовать |
|---|---|
| Родитель, дети, _Ready, обработка ввода или кадров | Entity либо подходящий подкласс |
| Положение в 2D или 3D | Entity2D или Entity3D |
| Общие редактируемые и сохраняемые настройки | Resource |
| Расчёт здоровья, стоимость покупки, преобразование данных | Обычный C#-класс или метод |
| Множество однородных чисел для расчёта | Подходящая коллекция, а не отдельный Entity на каждое число |
HealthModel ниже не зависит от движка. Его можно создать, вызвать и проверить без уровня, пути или _Ready. IDamageable задаёт доступную команду.
HealthModel.cs
using System;
public interface IDamageable
{
bool TryApplyDamage(int amount);
}
public sealed class HealthModel : IDamageable
{
public int Maximum { get; }
public int Current { get; private set; }
public HealthModel(int maximum)
{
if (maximum <= 0) throw new ArgumentOutOfRangeException(nameof(maximum));
Maximum = maximum;
Current = maximum;
}
public bool TryApplyDamage(int amount)
{
if (amount <= 0 || Current == 0) return false;
Current = amount >= Current ? 0 : Current - amount;
return true;
}
}Когда обёртка Entity всё-таки нужна
DamageReceiver из полного примера связывает модель с жизненным циклом, экспортом настроек и движковым сигналом. Разделяйте эти обязанности только там, где это упрощает код; создавать интерфейс и отдельный класс для каждого свойства не требуется.
Обычный C#-объект не получает автоматической сериализации в PackedEntity. Сохраните нужные значения отдельной схемой, если они должны переживать выход из игры.
Entity здесь — объект иерархии. Название не означает ECS, плотное хранение компонентов или автоматическую обработку больших миров. Выбор класса сам по себе не доказывает ускорение: измеряйте конкретную задачу.