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 monster | NPC с готовым графом диалога, подарка предмета или подарка монстра |
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
- Выберите GameObject актора.
- В Inspector найдите нужный слот графа (например, Interact Command Graph).
- Нажмите Edit graph, чтобы открыть окно редактора узлов. Delete graph очищает его.
Шаг 3: Добавьте узлы
- Щёлкните правой кнопкой в редакторе графа.
- Выберите Create Command /
<Категория>/<Узел>. Категория — это папка узла (см. ниже). - Соединяйте узлы, перетаскивая от выходного порта одного узла ко входному порту другого.
Шаг 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. Путь «проигрыш» выполняется, только если узел настроен так, чтобы не возрождать игрока после поражения.
Тестирование событий
- Войдите в Play Mode в редакторе.
- Подведите персонажа к актору.
- Нажмите кнопку взаимодействия.
- Граф выполняется, и вы можете наблюдать за его ходом.
Если граф ведёт себя не так, как ожидалось:
- Проверьте консоль на ошибки.
- Убедитесь, что упомянутые игровые переменные, предметы и монстры существуют.
- Убедитесь, что все выходные порты подключены — неподключённый порт молча завершает эту ветвь.
- Добавьте узел LogMessage, чтобы выводить значения во время выполнения.
Рекомендации
- Давайте акторам описательные имена. «NPC_Professor_Lab» лучше, чем «Actor (3)».
- Используйте игровые переменные для состояния. Не полагайтесь только на включение/выключение актора.
- Проверяйте обе ветви. Каждый узел
If...должен работать как для True, так и для False. - Делайте графы читаемыми. Используйте пространственную раскладку, чтобы ход был понятен. Группируйте связанные узлы.
- Переиспользуйте шаблоны. Когда у вас есть работающий NPC-продавец, дублируйте его и изменяйте для других магазинов.
- Сохраняйтесь перед тестированием. Изменения CommandGraph — это изменения на уровне сцены, которые могут пропасть при вылете Unity.
О стороне C# — запуске графа из кода или написании собственного узла — см. API CommandGraph.