Спроектируйте общую систему взаимодействия для мультиплеерной игры на Unreal Engine со множеством видов интерактивных объектов — двери, подбираемые предметы, рычаги, триггеры, — и новые типы добавляются по ходу проекта. Игрок должен фокусировать объект, на который смотрит, видеть для него контекстную подсказку и действовать с ним. Новые типы интерактивов должны добавляться без правки кода взаимодействия игрока (никакой растущей ветки по типам, о которой игрок обязан знать). Сессия сетевая, поэтому сам эффект взаимодействия (открытие двери, расход предмета) должен быть авторитетным на сервере и не решаться клиентом, тогда как поиск фокуса и подсказка могут быть локальными для действующего игрока. Опишите, как игрок обнаруживает интерактивы и обращается к ним обобщённо, как взаимодействие запрашивается и исполняется, где живёт авторитет, и компромиссы вашего подхода.
Определите общий интерфейс IInteractable с методом Interact(Instigator); двери и подбираемые предметы реализуют его. Игрок трейсом находит сфокусированный объект, вызывает Server RPC, и сервер авторитетно исполняет взаимодействие.
- ✗Кастовать к каждому конкретному классу вместо использования общего интерфейса
- ✗Исполнять взаимодействие на клиенте и реплицировать лишь результат
- ✗Опрашивать дистанцию каждый Tick вместо трейса по вводу
- →Как показать подсказку взаимодействия только для локально сфокусированного объекта?
- →Как обработать взаимодействие с длительностью, например удержание для открытия двери?
Ключевые классы
IInteractable—UINTERFACEсInteract(AActor* Instigator),CanInteract,GetInteractText.ADoor,APickup,ATriggerVolume— конкретныеActor'ы, реализующие интерфейс.UInteractionComponent—UActorComponentна игроке: трейсом ищет фокусную цель, шлёт Server RPC.UInteractPromptWidget— локальный виджет подсказки «Нажмите E».
Модель данных
Интерфейс развязывает игрока и объекты: игрок знает только IInteractable, не конкретные классы. Дверь хранит bIsOpen; подбор ссылается на UItemDataAsset; триггер хранит ссылку на цель или тег события.
Поток данных
UInteractionComponentкаждый кадр (или по таймеру) трейсит вперёд, находит ближайшийIInteractable.- Локально показывается подсказка через
GetInteractText— только на владеющем клиенте. - По нажатию → Server RPC
ServerInteract(Target). - Сервер проверяет
CanInteract(дистанция, состояние) и вызываетInteract. - Результат (
bIsOpenдвери, удаление подбора) реплицируется всем.
Репликация
Состояние объекта (открыта ли дверь, подобран ли предмет) — Replicated, с OnRep для анимации и звука. Само взаимодействие инициируется Server RPC. Подсказка и трейс — чисто локальные, не реплицируются. Триггеры обычно Server-only по логике, эффект — multicast.
Настройка дизайнером
Дверь, подбор, триггер — это Blueprint-классы, наследующие C++-базу и реализующие интерфейс. Дизайнер настраивает скорость двери, тип события триггера, ссылку на предмет в деталях актора. Новые типы интерактива добавляются как новые реализации интерфейса.
Компромиссы
- Интерфейс vs. общий базовый класс: интерфейс гибче (актор может быть и интерактивом, и чем-то ещё),
базовый классудобнее для общего кода. Часто комбинируют. - Трейс по вводу vs. overlap: трейс точнее для «смотрю на объект»; overlap проще для зон, но менее предсказуем при множестве объектов.