Универсальная система используемых предметов
Обзор
Система построена на принципах наследования и интерфейсов. Любой предмет в руках может реализовывать интерфейс IUseable и иметь свою уникальную логику использования.
Архитектура
IUseable
Интерфейс для всех используемых предметов:
CanUse()- проверка возможности использованияUse()- выполнение действияCooldown- время перезарядки между использованиями
BaseWeapon
Базовый класс для оружия, наследуется от InventoryItem и реализует IUseable. Содержит:
- Логику стрельбы и трассировки пуль
- Управление патронами (магазин + инвентарь)
- Систему перезарядки
- Эффекты выстрела и попадания
- Автоматическую стрельбу
- Физику - автоматическое отключение RigidBody при экипировке
Flashlight
Пример другого используемого предмета - фонарика. Показывает:
- Как создавать предметы с собственной логикой
- Переключение состояний (вкл/выкл)
- Звуковые эффекты
WeaponFactory
Универсальная фабрика для создания любых используемых предметов.
Ключевые особенности
1. Наследование от InventoryItem
- BaseWeapon наследуется от InventoryItem - не нужно вешать 2 компонента на префаб
- Один компонент = один предмет в инвентаре
- Автоматическое управление состоянием экипировки
2. Автоматическая стрельба
- Оружие стреляет автоматически при удержании кнопки мыши только если IsAutomatic = true
- Для полуавтоматического оружия (IsAutomatic = false) - только одиночные выстрелы
- Частота стрельбы берется из WeaponItemDefinition.FireRate
3. Система патронов
- Оружие начинается с пустым магазином - патроны нужно зарядить
- Сохранение патронов в магазине - при выбрасывании оружия патроны остаются
- Патроны хранятся в инвентаре как отдельные предметы
- Стрельба зависит ТОЛЬКО от патронов в магазине - CurrentAmmo
- HUD показывает патроны в магазине - не зависит от инвентаря
- Патроны тратятся только из магазина при выстреле - CurrentAmmo уменьшается
- Патроны тратятся из инвентаря только при перезарядке - загружаются в магазин
- Перезарядка только вручную - кнопка R или автоматически при пустом магазине
- Безопасная обработка неполных магазинов - загружается столько патронов, сколько есть в инвентаре
4. HUD и UI
- Отображение патронов в магазине (текущие/максимум)
- Отображение патронов в инвентаре (общее количество)
- Прогресс перезарядки в реальном времени
- Формат:
15/30 (45)- где 15 в магазине, 30 максимум, 45 всего в инвентаре
5. Физика
- Автоматическое отключение RigidBody при экипировке
- Включение физики при снятии оружия
- Предметы не падают когда в руках
6. Настройка в префабах
- Не нужно создавать отдельные файлы для каждого оружия
- Настройка происходит прямо в инстансе префаба
- Компоненты добавляются автоматически
Практическое использование
1. Создание оружия в редакторе
Шаг 1: Создание префаба
- Создайте новый GameObject в сцене
- Добавьте модель оружия (SkinnedModelRenderer)
- Добавьте компонент
BaseWeapon - Настройте параметры в инспекторе:
GunRenderer- ссылка на рендерер оружияMuzzleLight- свет вспышкиParticlePrefab- эффекты попаданияBloodParticle- эффекты кровиCooldown- время между выстрелами
Шаг 2: Создание WeaponItemDefinition
- В Project Settings создайте новый ресурс типа "Weapon Item Definition"
- Настройте параметры:
Name: "Pistol" Slot: RightHand HoldType: Pistol Damage: 25 FireRate: 8 Range: 1000 MagazineSize: 15 AmmoType: "Pistol" ReloadTime: 2.0 Spread: 0.02 - Укажите префаб в поле
Prefab
Шаг 3: Добавление в игру
// В коде игрока или менеджера
var weaponDef = ResourceLibrary.Get<WeaponItemDefinition>("Items/pistol.weapon");
var weaponItem = WeaponFactory.CreateWeaponItem(weaponDef);
player.Inventory.AddItem(weaponItem);
2. Создание фонарика
Шаг 1: Создание префаба фонарика
- Создайте GameObject с моделью фонарика
- Добавьте компонент
Flashlight - Настройте параметры:
LightSource- GameObject с источником светаToggleSound- звук включения/выключенияCooldown- время между переключениями
Шаг 2: Создание ItemDefinition
// Создайте BaseItemDefinition или WeaponItemDefinition
// Name: "Flashlight"
// Slot: LeftHand
// Prefab: ссылка на префаб фонарика
Шаг 3: Использование
var flashlightDef = ResourceLibrary.Get<BaseItemDefinition>("Items/flashlight.item");
var flashlightItem = WeaponFactory.CreateItem(flashlightDef);
player.Inventory.AddItem(flashlightItem);
3. Создание собственного предмета
// Создайте новый класс
public sealed class Medkit : Component, IUseable
{
[Property] public float Cooldown { get; set; } = 5f;
[Property] public int HealAmount { get; set; } = 50;
private TimeSince _lastUseTime;
public bool CanUse()
{
return IsValid && _lastUseTime >= Cooldown;
}
public void Use()
{
if (!CanUse()) return;
_lastUseTime = 0;
// Логика лечения
var player = Dedugan.Local;
if (player != null)
{
player.Health = Math.Min(player.Health + HealAmount, 100);
Log.Info($"Игрок вылечен на {HealAmount} HP");
}
}
}
WeaponFactory - подробное руководство
Основные методы:
1. CreateUseableItem(BaseItemDefinition, InventoryItem)
Создает любой используемый предмет:
var itemDef = ResourceLibrary.Get<BaseItemDefinition>("path/to/item");
var item = WeaponFactory.CreateUseableItem(itemDef, inventoryItem);
2. CreateWeapon(WeaponItemDefinition, InventoryItem)
Создает оружие (для обратной совместимости):
var weaponDef = ResourceLibrary.Get<WeaponItemDefinition>("path/to/weapon");
var weapon = WeaponFactory.CreateWeapon(weaponDef, inventoryItem);
3. CreateItem(BaseItemDefinition)
Создает предмет для инвентаря:
var itemDef = ResourceLibrary.Get<BaseItemDefinition>("path/to/item");
var inventoryItem = WeaponFactory.CreateItem(itemDef);
Автоматическое определение типа
WeaponFactory автоматически определяет тип предмета по имени:
- Оружие: содержит "pistol", "rifle", "gun" → создается
BaseWeapon - Фонарик: содержит "flashlight", "light" → создается
Flashlight - По умолчанию: создается
BaseWeapon
Примеры использования
Создание пистолета:
// 1. Создаем предмет для инвентаря
var pistolDef = ResourceLibrary.Get<WeaponItemDefinition>("Items/pistol.weapon");
var pistolItem = WeaponFactory.CreateWeaponItem(pistolDef);
// 2. Добавляем в инвентарь
player.Inventory.AddItem(pistolItem);
// 3. Экипируем
player.Inventory.EquipItem(pistolItem);
Создание фонарика:
// 1. Создаем предмет
var flashlightDef = ResourceLibrary.Get<BaseItemDefinition>("Items/flashlight.item");
var flashlightItem = WeaponFactory.CreateItem(flashlightDef);
// 2. Добавляем в инвентарь
player.Inventory.AddItem(flashlightItem);
Создание аптечки:
// 1. Создаем предмет
var medkitDef = ResourceLibrary.Get<BaseItemDefinition>("Items/medkit.item");
var medkitItem = WeaponFactory.CreateItem(medkitDef);
// 2. Добавляем в инвентарь
player.Inventory.AddItem(medkitItem);
Настройка в префабах
Для оружия:
- Добавьте компонент
BaseWeapon - Настройте все необходимые ссылки (рендерер, звуки, эффекты)
- Установите параметры стрельбы (Cooldown, FireRate и т.д.)
Для других предметов:
- Добавьте компонент, реализующий
IUseable - Настройте специфичные параметры
- Реализуйте логику в методах
CanUse()иUse()
Преимущества системы
- Универсальность - один интерфейс для всех предметов
- Гибкость - каждый предмет может иметь свою логику
- Простота - настройка в префабах, без создания отдельных файлов
- Расширяемость - легко добавлять новые типы предметов
- Производительность - кэширование и оптимизация
- Читаемость - понятная структура и документация
Примеры предметов
- Оружие - стрельба, перезарядка, патроны
- Фонарик - включение/выключение света
- Аптечка - лечение игрока
- Инструменты - ремонт, строительство
- Еда - восстановление здоровья/голода