Здесь не будет ничего про скрипты.
Долго думаю над ИИ, в задумке у него должна быть такая структура:
Чтобы унифицировать создание врагов с разными возможностями, решил сделать по отдельному скрипту для разных состояний персонажа, в к-й он реализует одну возможность:
CharacterPhysics - физика перемещения и столкновений, независимо от CC или Rigidbody, для перемещаемых объектов.
MovementCtl - передвижение по уровню
JumpCtl - прыганье и паданье
LadderCtl - лазанье по лестницам и веревкам
InteractCtl - процедуры взаимодействия с объектами
В дальнейшем можно будет усложнять каждый механизм путем создания дочернего класса.
На данный момент никак не могу решить - как связать мозг (принятие решений) с средствами действия (инструмент). Вроде бы связь должна быть двусторонней - не только мозг может приказывать рукам и ногам совершить действия, но и может опрашивать их состояние:
0 - средство заблокировано (либо непрерываемое действие)
1 - занято (уже выполняется действие, но его можно прервать)
2 - свободно
Так мозг определяет какие действия можно совершить в соответствии со свободными средствами:
0) Руки и ноги заблокированы: Ничего
1) Свободны руки: Бить, Взаимодействовать
2) Свободны ноги: Прыгать, Сесть на корточки
3) Свободны руки и ноги: Залезть на лестницу
4) Заняты руки: Использовать, Бросить
5) Заняты ноги: Идти, Бежать
6) Заняты руки и ноги: Отцепиться, Спрыгнуть
В общем, связи между скриптами выглядят так (извините за отвратное качество):
Сейчас могз просто записывает в переменные начала и конца действия, а средства (Ctl-скрипты) их читают. Надо бы наоборот - чтобы могз вызывал функции в PoseCtl и он уже влиял на остальные скрипты.
Вопрос вот в чем. Как обстрагировать мозг (на рисунке PlayerControls) от набора Ctl-скриптов, чтобы он общался только с PoseCtl? Сейчас я склоняюсь в пользу следующего варианта.
Скрипт PoseCtl хранит в себе текущее состояние персонажа (pose) и его стадию (stage), а также состояния средств (руки, ноги, речь). В момент старта сцены каждый Ctl-скрипт регистрирует PoseCtl свою функцию, записывая ее в в делегат, соответствующий обрабатываемой позе. Эта функция вызывается внутри Update и занимается управлением тела персонажа (анимация, команды перемещения по сцене в зависимости от stage).
Мозг анализирует состояния средств и вызывает функции в PoseCtl, но это на самом деле не функции, а тоже делегаты. После смены позы персонажа вызывается зарегистрированная на эту позу функция и она меняет эти делегаты в зависимости от того, какие действия можно выполнять. Например, на лестнице нельзя присесть и взаимодействовать с объектами. Поэтому когда мозг пошлет команду "Interact" и текущим объектом будет лестница, то вызовется функция ClimbLadder в LadderCtl. Она сделает ноги и руки занятыми, обнулит (присвоит пустую функцию) делегатам Crouch и Interact и поменяет функции на делегатах Move, Run и Jump на свои.
Пример 2, сидя на корточках, допустим, нельзя прыгать и бежать. Когда пользователь нажмет кнопку "вниз" и ноги будут свободны, то скрипт вызовет делегат Crouch в PoseCtl. В состоянии "стоя" этот делегат будет зарегистрирован в MovementCtl на функцию CrouchOn. Эта функция сотрет делагаты Run и Jump, а также перепишет делегаты Move, Crouch и Interact.
Как думаете, подойдет такой способ или есть что попроще?