Оптимальный способ подбора предметов в Unity 3d

Делаю небольшую игру. Пришло время создать систему предметов, которые будут выпадать в рандомных точках локации. Мне нужно, чтобы после подбора предмета он отображался на экране, чтобы игрок видел, что у него есть, например, броня, или, если игрок подбирает патроны, у него изменялось значение в соответствующей переменной. Мой способ реализации примерно такой:

  1. Сделать коллекцию item ов , присвоить им ID.
  2. Через скрипт игрока написать onTriggerEnter и в нем if ами прописывать. "Если ID предмета такой то - добавить, например, жизнь на экран или патроны Все бы ничего, но мне кажется, этот способ очень корявый, хоть и, наверное, самый простой. Есть что то оптимальнее?

Ответы (1 шт):

Автор решения: Yaroslav

Правильный способ это всегда разделение на маленькие и простые ответственности. Например:

  • На игроке есть некий компонет ItemPicker с единственным методом Pick(PickableItem item)

  • Подбираемый предмет сам реагирует на коллекторов как ему нужно, какие-то могут подбираться на расстоянии например патроны и валюта, к другим нужно близко подойти, например хилки. Предметы могут реагировать на OnCollisionEnter или считать дистанцию или смешенный вариант для разных типов. Отдавая полномочия подбора коллектору закрываются возможности реализаций и навешивая сразу две ответственности.

  • Соответственно на предмете несколько компонентов. PickDetector отвечает за фиксацию подбирания тем или иным способом после чего происходит событие передающее Picker и отключение. На событие может сработать компонент анимирующий полет до пикера, после чего передать пикеру компонент PickableItem который может быть чем угодно.

  • ItemPicker должен выступать в виде визитера (паттерн visitor). То-есть все предметы реализуют класс унаследованные от PickableItem, например PickableAmmo или PickableHealth. Метод Pick не совсем один, а имеет соответствующий набор перегрузок Pick(PickableAmmo ammo), Pick(PickableHealth health) и в зависимости от типа он сработает необходимый или базовый для неопределенного перегрузкой предмета. Под каждый тип есть события Action<AmmoType, int> PickedAmmo, Action<int> PickedHealth на которые и подписаны все заинтересованные не получая лишнего и даже не зная о существовании никаких PickableItem, а сразу конкретные значения, сколько хп или сколько амуниции T типа подобранно.


public abstact class PickableItem : MonoBehavour 
{ }

public enum AmmoType { Pistol, Rifle, Shotgun }

public class PickableAmmo : PickableItem
{
    public AmmoType Type;
    public int Amount;
}

public class PickableHealth : PickableItem
{
    public int Amount;
}

Итого 4 ответственности:

  • ItemPicker сообщает о подобранном в отсортированном виде для разных подписчиков
  • PickDetector отвечающий за подбор
  • PickAnimation отвечающий за полет до пикера или просто эффект вспышки символизирующий подбирание. (опционально)
  • PickableItem и его наследники содержащие информацию о том что находится в подобранном предмете.
→ Ссылка