Перейти к основному содержимому

CommandGraph: скриптинг событий на узлах

CommandGraph — это система визуального скриптинга MCE для создания поведения NPC, кат-сцен, квестов и интерактивных событий. Она предоставляет редактор на узлах, где вы соединяете команды, чтобы определить последовательность событий, — без кода на C#.

Это основной инструмент для гейм-дизайнеров, работающих с MCE во всех редакциях, включая скомпилированные редакции, в которые исходный код не входит.

Что создаёт граф

Это окно — результат работы графа из двух узлов: вывески, с которой взаимодействовал игрок, и одной команды ShowSignDialog. Ничего из этого не написано на C#: та же форма масштабируется до ветвящейся кат-сцены, и рантайм не видит разницы.

Что такое CommandGraph?​

CommandGraph (ActorCommandGraph) — это граф узлов, хранящийся в Actor (любой интерактивной сущности мира). Когда актор запускается, граф выполняется как корутина, узел за узлом.

У каждого актора есть несколько слотов графов — по одному на каждый момент, на который вы можете захотеть отреагировать:

СлотВыполняется
On Enable Command GraphКогда актор включается.
Loop Command GraphСнова и снова, пока не выполняется ни один другой граф актора.
Interact Command GraphКогда игрок взаимодействует с актором.
On Demand Command Graph 0 to 3Только когда другой граф запрашивает его (RunOnDemand, RunMultipleOnDemand).

Специализированные акторы добавляют собственные слоты: у TriggerActor есть графы «игрок вот-вот войдёт / вошёл / вот-вот будет телепортирован / телепортирован» и «актор вытолкнут внутрь», у ActorCharacter — граф «spot player», у PushableActor — граф «push».

Представляйте граф как визуальный скрипт, где каждый узел — игровое действие:

[Root] → [ShowDialog] → [IfPlayerHasBadge]
├─ True → [GivePlayerItem] → ...
└─ False → [ShowDialog: "Come back later"]

Создание первого события​

Шаг 1: Создайте актора​

Быстрее всего через меню Hierarchy: щёлкните правой кнопкой и выберите GameObject > MCE > один из готовых акторов:

МенюСоздаёт
Blank/Character, Blank/EmptyTrigger, Blank/InvisibleПустого персонажа, триггер или невидимого актора, который вы заполняете сами
NPCs/Simple dialog, NPCs/Give item, NPCs/Give monsterNPC с готовым графом диалога, подарка предмета или подарка монстра
Trainers/Static, Circle, Look around, Random look around, Random walkТренеров с обычным поведением
Other/Sign, Pick up item, срубаемые деревья, разбиваемые камни, валуны, водоворотыКлассические предметы мира

Компонент можно добавить и самостоятельно. Конкретные типы акторов:

Тип актораТриггерПрименение
SimpleActorИгрок взаимодействует (без графики и дополнительной логики)Невидимые точки взаимодействия
ActorCharacterИгрок взаимодействует; может ходить, осматриваться и замечать игрокаNPC, тренеры
TriggerActorИгрок наступает на него (не блокирует движение)Автоматические триггеры, варпы, скрытые события
ActorItemИгрок взаимодействует, получает предмет, и актор исчезаетПредметы на земле
PushableActorИгрок толкает его (это ActorCharacter)Валуны, блоки-головоломки

Actor и GridSubscribingActor — абстрактные базовые классы; напрямую их не добавляют.

Шаг 2: Откройте редактор CommandGraph​

  1. Выберите GameObject актора.
  2. В Inspector найдите нужный слот графа (например, Interact Command Graph).
  3. Нажмите Edit graph, чтобы открыть окно редактора узлов. Delete graph очищает его.

Шаг 3: Добавьте узлы​

  1. Щёлкните правой кнопкой в редакторе графа.
  2. Выберите Create Command / <Категория> / <Узел>. Категория — это папка узла (см. ниже).
  3. Соединяйте узлы, перетаскивая от выходного порта одного узла ко входному порту другого.

Шаг 4: Настройте узлы​

Щёлкните узел, чтобы изменить его поля на панели Inspector: текст диалога, предмет и количество подарка, тайл телепорта, переменную условия.

Категории узлов​

Это категории в том виде, в каком они появляются в меню Create Command. В списке ниже названы самые полезные узлы каждой; полный набор — в меню.

Dialogs​

УзелОписание
ShowDialogПоказать обычный диалог
ShowChoiceDialogПоказать диалог, где игрок делает выбор (по одному выходному порту на вариант)
ShowSignDialogПоказать диалог вывески
ShowNoSkippableDialogПоказать диалог, который игрок не может пропустить
NextDialogПерейти к следующему диалогу
ShowUsedMoveDialogДиалог о том, что монстр применил приём
ShowMonsterPictureПоместить изображение монстра спереди в рамку или убрать его

Variables​

Условия и изменения переменных. У каждого узла If... два выходных порта — True и False.

УзелОписание
SetBoolVariable, SetIntVariableЗадать игровую переменную
IfBool, IfIntEquals, IfIntCompareВетвление по bool или по int, сравниваемому со значением (меньше, больше, равно...)
IfIntVariablesCompareСравнить одну int-переменную с другой int-переменной
SwitchIntVariableПо одному выходному порту на каждое значение int-переменной
WhileBool, WhileConditionЦикл, пока выполняется условие
IfPlayerCharacterIs, IfPlayerDirectionIsВетвление по выбранному персонажу-игроку или по направлению его взгляда
SetTemporalBoolVariable, SetTemporalIntVariable, IfTemporalBoolПеременные выполняющегося актора, которые не сохраняются вместе с игрой

Игровые переменные выбираются через ссылку на переменную (глобальное хранилище или хранилище сцены). Они сохраняются в данных сохранения и могут читаться из любого графа или скрипта.

Items​

УзелОписание
GivePlayerItem, TakePlayerItemДобавить предмет в сумку игрока или забрать его
GivePlayerMoneyДать игроку деньги
IfPlayerHasItemВетвление по наличию у игрока предмета
ChooseItemDialogПопросить игрока выбрать предмет и выполнить соответствующие команды

Monsters​

УзелОписание
GiveMonstersДать игроку монстров (фиксированный вид или случайный). В онлайн-слое нужен grant id: см. Подарки монстров
HealPlayerRosterВылечить всю команду
ChooseMonsterDialog, ChooseTwoMonstersDialogПопросить игрока выбрать одного или двух монстров
ChangeMonsterNickname, RemoveMonsterNicknameПереименовать монстра
MoveTutor, RemindPreviouslyLearntMovesНаучить приёму или напомнить прежние приёмы
IfMonsterCanLearnMove, IfRosterHasMoveВетвление по приёмам
OpenStorageОткрыть хранилище монстров

Battles​

УзелОписание
SingleTrainerFightСразиться с одним тренером
SingleWildFight, DoubleWildFightЗапустить сражение с дикими монстрами
FightFromTemplateЗапустить сражение из шаблона сражения
RandomFightAgainstRandomRostersСлучайное сражение с одной или двумя случайными командами
StartTowerRunНачать забег по Боевой башне
IfCanHaveDoubleBattleВетвление по тому, возможно ли парное сражение

Badges, Dex, Quests​

УзелОписание
GiveBadge, IfPlayerHasBadgeВыдать значок / проверить его наличие
GiveDex, IfPlayerHasDex, IfDexIsComplete, RegisterMonsterAsSeenРабота с дексом
StartQuest, UpdateQuestObjective, ProgressQuestObjective, CompleteQuest, FailQuestПрогресс квестов (см. Система квестов)
IfPlayerHasQuest, IfCompletedQuest, IfQuestFailed, IfCurrentQuestObjectiveВетвление по состоянию квеста

Animations​

Персонажи, игрок и экран.

УзелОписание
Move, MovePlayer, WalkToPlayerПровести персонажа, игрока или персонажа к игроку
Look, LookAtPlayer, ForcePlayerToLookПовернуть персонажа
JumpCharacter, WanderWithinRangeПрыжок; блуждание вокруг начального тайла
HideCharacter, ShowCharacter, HidePlayer, ShowPlayerПоказать или скрыть графику
MoveFollower, LookFollowerПровести или повернуть монстра, идущего за игроком
FadeScreenToBlack, OpenDoorЗатемнить экран; открыть дверь на тайле актора
PlayExclamation, PlayEmotionПоказать шарик над персонажем: см. Эмоциональные шарики и эмоции

Sounds​

УзелОписание
PlayMusic, StopMusic, SaveMusic, RestoreSceneMusicМузыка мира поверх собственной музыки карты
PlaySound, PlayMonsterCry, WaitForAudioЗвуки и крики

Shops, Trade, Saves, Breeding​

УзелОписание
BuyInShop, SellInShopВыполнить логику магазина для покупки или продажи
TradeSelectedMonsterОбменять монстра, выбранного игроком
AutoSaveIfEnabledАвтосохранение, если включено в конфигурации
StoreTwoSelectedMonstersInNursery, IfEggIsReady, BreedEggInNurseryAndGiveToPlayerПитомник

Utils​

УзелОписание
TeleportPlayerТелепортировать игрока в другое место (при игре онлайн проверяется сервером)
TeleportActorInsideScene, PlaceActorПереместить актора внутри текущей сцены
WaitTime, LoopXTimes, RunInParallelВремя и поток выполнения
LockPlayerInputЗаблокировать или разблокировать движение игрока во время кат-сцены
SetActorActive, AutoDestroyВыключить другой объект или уничтожить актора
SwitchOnDayMoment, SwitchTimeOfDayВетвление по времени суток или его установка
SetLastHealLocation, SetLastHealLocationToCurrentГде игрок возрождается после проигрыша
LogMessageЗаписать сообщение в консоль

Соединение узлов​

CommandGraph использует потоковую модель соединений:

  • Каждый граф начинается с узла Root.
  • У каждого узла есть входной порт и один или несколько выходных портов.
  • У большинства узлов ровно один выходной порт (следующая команда). У узлов If... — True и False; у ShowChoiceDialog — по порту на вариант; у SwitchOnDayMoment — по порту на время суток.
  • Узел без подключённого выходного порта завершает эту ветвь графа.

Пример: NPC-продавец​

[Root]
→ [ShowDialog: "Welcome! Would you like to browse my wares?"]
→ [ShowChoiceDialog: "Buy" / "Sell" / "No thanks"]
├─ "Buy" → [BuyInShop]
├─ "Sell" → [SellInShop]
└─ "No thanks" → [ShowDialog: "Come back anytime!"]

Пример: выдающий квест​

[Root]
→ [IfBool: rescued_lost_monster]
├─ True → [IfBool: quest_reward_given]
│ ├─ True → [ShowDialog: "Thanks again!"]
│ └─ False → [GivePlayerItem: TM, 1]
│ → [SetBoolVariable: quest_reward_given = true]
│ → [ShowDialog: "Take this as thanks!"]
└─ False → [ShowDialog: "Please help me find my lost monster!"]
→ [SetBoolVariable: quest_find_monster = true]

Пример: лидер зала​

[Root]
→ [IfPlayerHasBadge: Boulder Badge]
├─ True → [ShowDialog: "You've already proven yourself!"]
└─ False
→ [ShowDialog: "I am the Gym Leader! Prepare for battle!"]
→ [SingleTrainerFight]
├─ On Player Won → [ShowDialog: "Impressive! You've earned this."]
│ → [GiveBadge: Boulder Badge]
└─ On Player Lost → [ShowDialog: "Train harder and come back!"]

У SingleTrainerFight три выходных порта: обычный порт следующей команды, On Player Won и On Player Lost. Путь «проигрыш» выполняется, только если узел настроен так, чтобы не возрождать игрока после поражения.

Тестирование событий​

  1. Войдите в Play Mode в редакторе.
  2. Подведите персонажа к актору.
  3. Нажмите кнопку взаимодействия.
  4. Граф выполняется, и вы можете наблюдать за его ходом.
Отладка графа

Если граф ведёт себя не так, как ожидалось:

  1. Проверьте консоль на ошибки.
  2. Убедитесь, что упомянутые игровые переменные, предметы и монстры существуют.
  3. Убедитесь, что все выходные порты подключены — неподключённый порт молча завершает эту ветвь.
  4. Добавьте узел LogMessage, чтобы выводить значения во время выполнения.

Рекомендации​

  1. Давайте акторам описательные имена. «NPC_Professor_Lab» лучше, чем «Actor (3)».
  2. Используйте игровые переменные для состояния. Не полагайтесь только на включение/выключение актора.
  3. Проверяйте обе ветви. Каждый узел If... должен работать как для True, так и для False.
  4. Делайте графы читаемыми. Используйте пространственную раскладку, чтобы ход был понятен. Группируйте связанные узлы.
  5. Переиспользуйте шаблоны. Когда у вас есть работающий NPC-продавец, дублируйте его и изменяйте для других магазинов.
  6. Сохраняйтесь перед тестированием. Изменения CommandGraph — это изменения на уровне сцены, которые могут пропасть при вылете Unity.

О стороне C# — запуске графа из кода или написании собственного узла — см. API CommandGraph.