跳到主要内容

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——一个恰好只有一个输出端口(NextCommand) 的 CommandNode。分支节点(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;
}
}
}