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

CommandGraph

Узловая система визуального скриптинга, управляющая поведением NPC и событий — диалоги, ветвления, выдача предметов/денег, телепорты, бои, квесты и другое. Каждый интерактивный актёр владеет ActorCommandGraph; граф создаётся в редакторе и выполняется как корутина во время выполнения.

Namespace: OpenMon.MCE.Actors.CommandGraph

Создаётся в редакторе, выполняется в рантайме

Обычно графы команд строятся в визуальном редакторе (см. руководство по CommandGraph), а не из C#. Приведённая ниже рантайм-поверхность — это то, к чему вы обращаетесь при расширении системы собственным узлом или программном запуске графа. Сами типы узлов (ShowDialog, GivePlayerItem, TeleportPlayer, …) — это создаваемые ассеты: их поля сериализуются в инспекторе, это не API для кода.

ActorCommandGraph​

Контейнер графа одного актёра.

[Serializable]
public class ActorCommandGraph
{
public bool IsRunning { get; }

[SerializeReference] public CommandNode RootNode;
[SerializeReference] public List<CommandNode> Nodes;

public bool IsGraphEmpty { get; }

public IEnumerator Run(CommandParameterData parameterData,
Action<bool> onLoopRunningUpdatedCallback = null);

public CommandNode CreateNode(Type type, Vector2 position = default);
public void DeleteNode(CommandNode node);
public void ConnectNodes(CommandNode parent, CommandNode child, int parentIndex);
public void RemoveConnection(CommandNode parent, CommandNode child, int parentIndex);
public List<CommandNode> GetChildren(CommandNode node);
}

IsRunning​

Выполняется ли этот граф в данный момент.

Тип: bool (только чтение)

RootNode​

Входной CommandNode (RootNode), с которого начинается выполнение. Сериализуется по ссылке, чтобы полиморфные типы узлов корректно сохранялись и загружались.

Тип: CommandNode

Nodes​

Все узлы графа, включая недостижимые из RootNode (хранятся, чтобы редактор мог сохранять осиротевшие/несоединённые узлы).

Тип: List<CommandNode>

IsGraphEmpty​

true, когда нет корневого узла или у корня нет детей.

Тип: bool (только чтение)

Run(CommandParameterData parameterData, Action<bool> onLoopRunningUpdatedCallback = null)​

Выполняет граф. Устанавливает IsRunning, затем запускает RootNode.RunCommandAndContinue, прокидывая контекст CommandParameterData через каждый узел.

Возвращает: IEnumerator — используйте yield из корутины.

CreateNode(Type type, Vector2 position = default) / DeleteNode / ConnectNodes / RemoveConnection​

Изменение графа для редактора: создать узел подкласса CommandNode, удалить его, соединить/ разъединить связи родитель→ребёнок по индексу выходного порта.

CommandNode​

Абстрактный базовый класс, от которого наследуется каждый тип узла.

[Serializable]
public abstract class CommandNode : MonsterDatabaseData<CommandNode>
{
public bool IsRunning { get; }
public string name;
public string GUID;
public Vector2 Position;
public Action OnPortsUpdated;

public virtual IEnumerator RunCommandAndContinue(CommandParameterData parameterData);

protected abstract IEnumerator Run(CommandParameterData parameterData,
Action<CommandParameterData> callback);

public abstract List<string> GetInputPorts();
public abstract List<string> GetOutputPorts();
public abstract void AddChild(CommandNode child, int index);
public abstract void RemoveChild(CommandNode child, int index);
public abstract List<CommandNode> GetChildren();
public abstract List<CommandNode> GetIndexedChildren();
}

RunCommandAndContinue(CommandParameterData parameterData)​

Выполняет этот узел (через абстрактный Run), затем переходит к его детям. Обрабатывает блокировку цикла, когда граф выполняется в петле.

Run(CommandParameterData parameterData, Action<CommandParameterData> callback)​

protected abstract — фактическая работа узла. Переопределите его в собственном узле. По завершении вызовите callback с (возможно изменёнными) данными параметров.

GetInputPorts() / GetOutputPorts()​

Именованные входные/выходные порты, которые узел предоставляет графу редактора. Линейный узел имеет один безымянный порт с каждой стороны; узел ветвления предоставляет по одному выходу на ветвь.

Возвращает: List<string>.

SingleExecutionPathCommandNode​

Большинство узлов наследуются от SingleExecutionPathCommandNode — CommandNode с ровно одним выходным портом (NextCommand). Узлы ветвления (If…, Switch…, While…) вместо этого предоставляют несколько выходных портов.

public abstract class SingleExecutionPathCommandNode : CommandNode
{
public CommandNode NextCommand;
// GetOutputPorts() => один безымянный порт; AddChild задаёт NextCommand.
}

CommandParameterData​

Контекст выполнения, прокидываемый через каждый узел во время прогона — поверхность, которую собственный узел читает и записывает.

public class CommandParameterData
{
public ActorCommandGraph Graph;
public GameObject Owner;
public Actor Actor;
public MCECharacterController.Direction PlayerDirection;
public PlayerCharacter PlayerCharacter;
public GlobalGameData GlobalGameData;
public MCESettings MCESettings;
public MonsterDatabaseInstance MonsterDatabase;
public IBattleLauncher BattleLauncher;
public ILocalizer Localizer;
public IConfigurationManager ConfigurationManager;
public IInputManager InputManager;
public PlayerTeleporter Teleporter;
public SavegameManager SavegameManager;
public MapSceneLauncher MapSceneLauncher;
public TimeManager TimeManager;
public QuestManager QuestManager;
public TradeManager TradeManager;
public bool UsingMove;
public MonsterInstance MoveUser;
public Move Move;
public bool IsRunningOnLoop;
public ICommandParameter[] ExtraParams;
public Action<CommandCallbackParams> Callback;
}

Категории встроенных узлов​

Узлы сгруппированы по папкам в Actors/CommandGraph/. Представительные типы:

КатегорияПримеры узлов
DialogsShowDialog, ShowChoiceDialog, ShowSignDialog, NextDialog
ItemsGivePlayerItem, GivePlayerMoney, IfPlayerHasItem, ChooseItemDialog
MonstersGiveMonsters, HealPlayerRoster, ChooseMonsterDialog, ChangeMonsterNickname
BattlesSingleWildFight, SingleTrainerFight, DoubleWildFight, StartTowerRun
BadgesGiveBadge, IfPlayerHasBadge
DexGiveDex, RegisterMonsterAsSeen, IfDexIsComplete
QuestsStartQuest, CompleteQuest, ProgressQuestObjective, IfCompletedQuest
VariablesSetBoolVariable, SetIntVariable, IfBool, IfCondition, WhileBool
UtilsTeleportPlayer, WaitTime, AutoSaveIfEnabled, SwitchTimeOfDay
AnimationsMove, Look, LookAtPlayer, WalkToPlayer, FadeScreenToBlack
Shops / TradeBuyInShop, SellInShop, TradeSelectedMonster

Написание собственного узла​

using System;
using System.Collections;
using System.Collections.Generic;
using OpenMon.MCE.Actors.CommandGraph;

namespace MyGame.Events
{
[Serializable]
public class LogStepsTaken : SingleExecutionPathCommandNode
{
protected override IEnumerator Run(CommandParameterData parameterData,
Action<CommandParameterData> callback)
{
// Читаем из общего контекста, прокинутого графом.
uint steps = parameterData.GlobalGameData.StepsTaken;
UnityEngine.Debug.Log($"Player has taken {steps} steps.");

callback(parameterData);
yield break;
}
}
}