Skip to content

指令便利 API(Command API) ​

指令便利 API 是对 指令系统 的高级封装,提供类型安全的流式接口,简化技能释放、移动、攻击等常见操作。

调用成功与实际完成的区别,以及排队、施法、取消和动画表现的完整流程,见指令与技能生命周期指南。

定义位置:TriggerEncapsulation.Commands

三层 API ​

层级适用场景示例
扩展方法 CommandExtensions简单操作,一行完成unit.CastAbility(abilityLink, target)
构建器 CommandBuilder需要自定义 Flag/Target/PlayerCommandBuilder.Create().WithAbility(...).AsUser().Execute(unit)
上下文 CommandContext批量操作,复用 Player/Flagcontext.CastAbility(...).Execute(unit)

扩展方法 ​

Entity 扩展 ​

csharp
// 技能
unit.CastAbility(abilityLink, target);
unit.ToggleAbility(abilityLink);
unit.TurnOnAbility(abilityLink);
unit.TurnOffAbility(abilityLink);

// 移动
unit.MoveInDirection(45f);              // 按角度
unit.MoveInDirection(new Angle(90f));   // 用 Angle 结构
unit.MoveTo(scenePoint);               // 移动到位置
unit.StopMovement();                    // 停止方向移动

// 攻击 / 停止
unit.AttackTarget(enemyUnit);
unit.Stop();                            // 清空指令队列

// 物品(需要 InventoryManager 组件)
unit.PickUpItem(pickUpItem);
unit.UseItem(item);
unit.DropItem(itemPickable);

所有 Entity 扩展方法共享参数 bool asUser = true, Player? player = null:

  • asUser: true(默认):设置 CommandFlag.IsUser,player 默认为 Player.LocalPlayer
  • asUser: false:不设置 IsUser/IsAI 标志,用于系统指令

Player 扩展 ​

操作玩家的 MainUnit:

csharp
player.CastAbilityWithMainUnit(abilityLink, target);
player.MoveMainUnitInDirection(angle);
player.MoveMainUnitTo(scenePoint);
player.StopMainUnit();

完整签名参考 ​

csharp
// Entity 技能扩展
static CmdResult CastAbility(this Entity unit, IGameLink<GameDataAbility> abilityLink,
    ICommandTarget? target = null, bool asUser = true, Player? player = null);
static CmdResult ToggleAbility(this Entity unit, IGameLink<GameDataAbility> abilityLink,
    bool asUser = true, Player? player = null);
static CmdResult TurnOnAbility(this Entity unit, IGameLink<GameDataAbility> abilityLink,
    bool asUser = true, Player? player = null);
static CmdResult TurnOffAbility(this Entity unit, IGameLink<GameDataAbility> abilityLink,
    bool asUser = true, Player? player = null);

// Entity 移动扩展
static CmdResult MoveInDirection(this Entity unit, float degrees,
    bool asUser = true, Player? player = null);
static CmdResult MoveInDirection(this Entity unit, Angle angle,
    bool asUser = true, Player? player = null);
static CmdResult MoveTo(this Entity unit, ScenePoint position,
    bool asUser = true, Player? player = null);
static CmdResult StopMovement(this Entity unit,
    bool asUser = true, Player? player = null);

// Entity 攻击/停止
static CmdResult AttackTarget(this Entity unit, Unit target,
    bool asUser = true, Player? player = null);
static CmdResult Stop(this Entity unit,
    bool asUser = true, Player? player = null);

// Entity 物品
static CmdResult PickUpItem(this Entity unit, IPickUpItem item,
    bool asUser = true, Player? player = null);
static CmdResult DropItem(this Entity unit, ItemPickable item,
    bool asUser = true, Player? player = null);
static CmdResult UseItem(this Entity unit, Item item,
    bool asUser = true, Player? player = null);

CommandBuilder ​

流式构建器,适合需要精细控制的场景。

csharp
var result = CommandBuilder.Create()
    .WithIndex(CommandIndex.Execute)
    .WithType(ComponentTagEx.AbilityManager)
    .WithAbility(abilityLink)
    .ToUnit(enemyUnit)
    .AsUser()
    .Execute(playerUnit);

构建器方法 ​

csharp
static CommandBuilder Create();

// 核心配置
CommandBuilder WithIndex(CommandIndex index);
CommandBuilder WithType(ComponentTag type);
CommandBuilder WithFlag(CommandFlag flag);
CommandBuilder WithPlayer(Player? player);
CommandBuilder WithTarget(ICommandTarget? target);
CommandBuilder WithAbility(IGameLink<GameDataAbility>? abilityLink);
CommandBuilder WithItem(Item? item);

// Toggle 技能
CommandBuilder WithToggle(IGameLink<GameDataAbility> abilityLink);
CommandBuilder WithTurnOn(IGameLink<GameDataAbility> abilityLink);
CommandBuilder WithTurnOff(IGameLink<GameDataAbility> abilityLink);

// 物品
CommandBuilder WithPickUp(IPickUpItem item);
CommandBuilder WithDrop(ItemPickable item);
CommandBuilder WithUse(Item item);

// 目标快捷方法
CommandBuilder ToUnit(Unit unit);
CommandBuilder ToPosition(ScenePoint position);
CommandBuilder ToAngle(Angle angle);
CommandBuilder ToAngle(float degrees);

// 上下文快捷方法
CommandBuilder AsUser(Player? player = null);   // 设置 IsUser + Player
CommandBuilder AsAI(Player player);              // 设置 IsAI + Player
CommandBuilder AsSystem();                       // 无标志,Player = null

// 执行
Command Build();
CmdResult Execute(Entity unit, bool testOnly = false);
CmdResult<T> Execute<T>(Entity unit, bool testOnly = false) where T : class;
(bool IsValid, string? ErrorMessage) Validate();

// 隐式转换
static implicit operator Command(CommandBuilder builder);

条件构建 ​

csharp
var builder = CommandBuilder.Create()
    .WithIndex(CommandIndex.Execute)
    .WithType(ComponentTagEx.AbilityManager)
    .WithAbility(abilityLink);

if (hasTarget)
    builder.ToUnit(target);
else if (hasPosition)
    builder.ToPosition(fallbackPosition);
else
    builder.ToAngle(facing);

var result = builder.AsUser().Execute(unit);

CommandContext ​

复用 Player 和 Flag 设置,适合批量操作。

创建上下文 ​

csharp
var userCtx   = CommandContext.ForUser(player);   // 用户操作
var aiCtx     = CommandContext.ForAI(aiPlayer);    // AI 操作
var systemCtx = CommandContext.ForSystem();        // 系统操作(绕过权限)

上下文方法 ​

返回 CommandBuilder,调用 .Execute(unit) 执行:

csharp
CommandBuilder CastAbility(IGameLink<GameDataAbility> abilityLink, ICommandTarget? target = null);
CommandBuilder MoveInDirection(Angle angle);
CommandBuilder MoveInDirection(float degrees);
CommandBuilder MoveTo(ScenePoint position);
CommandBuilder AttackTarget(Unit target);
CommandBuilder StopMovement();
CommandBuilder Stop();

BoundCommandContext ​

绑定到特定 Entity,免去每次传递参数:

csharp
var bound = unit.AsUser();          // 绑定用户上下文
bound.CastAbility(abilityLink, target);  // 直接执行,返回 CmdResult
bound.MoveInDirection(45f);
bound.AttackTarget(enemy);

var boundAI = unit.AsAI(aiPlayer);  // 绑定 AI 上下文
boundAI.MoveTo(patrolPoint);

通过 CommandContextExtensions 扩展创建:

csharp
static BoundCommandContext AsUser(this Entity entity, Player? player = null);
static BoundCommandContext AsAI(this Entity entity, Player? player = null);
static BoundCommandContext AsSystem(this Entity entity);

批量操作 ​

csharp
var aiCtx = CommandContext.ForAI(aiPlayer);
var targetPosition = GetPatrolPoint();

foreach (var unit in aiUnits)
{
    aiCtx.MoveTo(targetPosition).Execute(unit);
}

错误处理 ​

所有命令返回 CmdResult(或服务端 CmdResult<Order>)。

csharp
var result = unit.CastAbility(abilityLink, target);
if (!result.IsSuccess)
{
    Game.Logger.LogWarning("命令失败: {Error}", result.Error);
}

测试模式 ​

不实际执行,仅检查是否可行:

csharp
var testResult = unit.CastAbility(abilityLink, target, testOnly: true);
if (testResult.IsSuccess)
{
    unit.CastAbility(abilityLink, target);
}

服务端 Ability 实例重载 ​

服务端可直接使用 Ability 实例,跳过 GameLink 查找:

csharp
#if SERVER
// 扩展方法 — Ability 实例重载
unit.CastAbility(ability, target);
unit.ToggleAbility(ability);
unit.TurnOnAbility(ability);
unit.TurnOffAbility(ability);

// CommandBuilder — Ability 实例重载
CommandBuilder.Create().WithAbility(ability);
CommandBuilder.Create().WithToggle(ability);
CommandBuilder.Create().WithTurnOn(ability);
CommandBuilder.Create().WithTurnOff(ability);

// Player 扩展
player.CastAbilityWithMainUnit(ability, target);
#endif

底层类型 ​

CommandIndex ​

可扩展枚举,标识命令类型:

值说明
Execute执行(技能等)
TurnOn开启
TurnOff关闭
Toggle切换
Attack攻击
Move移动到位置
VectorMove方向移动
VectorMoveAdjust调整方向(不中断)
VectorMoveStop停止方向移动
Stop完全停止

物品相关(CommandIndexInventory):PickUp、Use、Swap、Give、Drop

CommandFlag ​

值说明
None无标志(系统操作)
IsUser用户操作
IsAIAI 操作
Queued加入队列
Preempt抢占
IsRequest请求类型(IsUser 或 IsAI)

ICommandTarget ​

命令目标接口,实现类型:Unit、ScenePoint、Angle、ItemPickable

客户端 vs 服务端 ​

  • 客户端:IssueOrder 发送 ProtoClientCommand 到服务端,不本地创建 Order
  • 服务端:IssueOrder 创建 Order 并加入 OrderQueue 执行

相关文档 ​