战斗 AI
MCE 为战斗 AI 使用可插拔的策略模式。每个 AI 都是一个 BattleAI ScriptableObject,而内置的 AI 被设计为可以串联:每种策略尝试做好自己的那件事,做不到时就把决定交给它的 Fallback AI。
AI 从不驱动战斗 —— 它只回答一个问题:“这位训练师现在会怎么做”, 而战斗循环决定何时发问。正是这种分离,让任何战斗都可以使用 不同的策略而无需触碰回合流程。
架构
BattleAI(命名空间 OpenMon.MCE.Battle.AI)要回答两件事:
RequestPerformAction—— 战斗者的回合。AI 以一个BattleAction回调,这是一个描述要做什么的小结构:战斗者(BattlerType和Index)、行动的Type(Move、Switch、Item或Run)、是否触发 Mega 形态(TriggerMegaForm),以及数值型的Parameters(哪个招式和哪个目标、哪个道具、哪只怪物)。RequestNewMonster—— 某只怪物濒死后,从队伍中派出哪一只。
它还有两个可选的钩子:OnBattlerFainted 和 OnBattleEnded(ML AI 用它们来给予奖励)。
一条链就是资产指向资产:
MegaOrGigaIfCan ──Fallback──▶ SwitchToEffectiveMonster ──Fallback──▶ PerformEffectiveMove ──Fallback──▶ PerformRandomMove ──Fallback──▶ RandomBattleAI
每个环节审视当前情况;如果满足条件就作答,否则询问它的 fallback。RandomBattleAI 是每条链的终点:它没有 fallback。
内置 AI 策略
它们都通过 Assets > Create > MCE > Battle > AI > ... 创建。
| 资产 | 作用 | 设置 |
|---|---|---|
| RandomBattleAI | 在随机招式和切换到随机怪物之间随机选择一个行动。用作最终的 fallback。 | -- |
| PerformRandomMove | 使用一个随机招式,若无可用招式则 fallback。 | Fallback |
| PerformEffectiveMove | 使用它拥有的最强有效伤害招式:任何高于阈值的都算有效;在有效招式中,优先选择多目标的,然后是威力更大的。当没有有效招式或几率判定失败时 fallback。 | EffectivenessThreshold(默认 1)、Chance(0-1)、Fallback |
| SwitchToEffectiveMonster | 带有一定随机性地切换到拥有有效招式的队伍成员。它也负责选择濒死后派出哪只怪物。 | EffectivenessThreshold、SwitchingChance(0-1)、Fallback |
| UseBattleItems | 在特定条件下使用战斗道具(HP 低于阈值时的恢复道具、列出的道具);否则 fallback。 | UseIfAvailable、UseOnOwnIfAvailable、HPThreshold、HPHealItems、Fallback |
| MegaOrGigaIfCan | 先向它的 fallback 询问行动,然后在战斗者能够时,将其标记为变为 Mega 或 giga 形态。 | Fallback |
| IfWildWithRunChanceRun | 如果怪物是野生的且其物种有逃跑几率,则在判定成功时逃跑;否则交给下一个。 | Fallback |
| MLBattleAI | 让训练好的 ML-Agents 大脑来决定(见下文)。 | AgentPrefab、Fallback |
为战斗选择 AI
战斗中的每支队伍由一个 BattleAI 控制:
- 对于普通遭遇 —— 由 CommandGraph 节点
SingleWildFight、DoubleWildFight和SingleTrainerFight发起的野生战斗和训练师战斗 ——BattleLauncher资产使用其 Default AI 字段。把它指向你想要的链的头部。 - 要给某场战斗专属的策略,使用
BattleTemplate(Create > MCE > Battle > Template):它的 AIs 数组为每支队伍保存一个BattleAI,与队伍、角色、背包和战斗的其他参数并列。FightFromTemplate节点会发起它。 - 在代码中,
BattleLauncher.LaunchBattle(...)直接接收 AI 数组。
示例链(你分配给 BattleLauncher 或模板的 AI 是列出的第一个):
简单(一号道路)
PerformRandomMove → RandomBattleAI
中等(道馆谜题)
MegaOrGigaIfCan → PerformEffectiveMove → PerformRandomMove → RandomBattleAI
困难(冠军)
MegaOrGigaIfCan → UseBattleItems (HP below 25%) → SwitchToEffectiveMonster → PerformEffectiveMove → PerformRandomMove → RandomBattleAI
编写你自己的 AI(Source 与 Studio 版本)
继承 BattleAI,实现两个抽象方法,并给你的类加上 [CreateAssetMenu]:
using System;
using System.Collections;
using System.Collections.Generic;
using OpenMon.MCE.Battle;
using OpenMon.MCE.Battle.AI;
using OpenMon.MCE.Configuration;
using UnityEngine;
[CreateAssetMenu(menuName = "MyGame/AI/Always Struggle", fileName = "AlwaysStruggle")]
public class AlwaysStruggle : BattleAI
{
[SerializeField] private BattleAI Fallback;
public override IEnumerator RequestPerformAction(MCESettings settings, BattleManager battleManager,
BattlerType type, int inBattleIndex,
Action<BattleAction> callback)
{
// Ask the next link of the chain, then adjust what it answered.
BattleAction action = default;
yield return Fallback.RequestPerformAction(settings, battleManager, type, inBattleIndex,
answer => action = answer);
callback(action);
}
public override int RequestNewMonster(MCESettings settings, BattleManager battleManager,
BattlerType type, int inBattleIndex, List<Battler> forbiddenBattlers) =>
Fallback.RequestNewMonster(settings, battleManager, type, inBattleIndex, forbiddenBattlers);
}
受保护的辅助方法 GenerateActionForMove(...) 为选定的 Move 构建 BattleAction(招式槽位和有效目标),静态方法 GetEnemies(battleManager, type) 返回正在战斗的对方战斗者。关于拥有这些 AI 的模块,参见 BattleManager API。
ML-Agents 集成
MCE 包含一个实验性的、基于 ML-Agents 的 AI。
MLBattleAI
使用 Unity ML-Agents,借助训练好的神经网络做出决策。
- 难度:可变(取决于训练)
- 用途:后期训练师、竞技 AI、研究
- 设置:需要
com.unity.ml-agents包和MCE_ML_AGENTS脚本宏定义;ML 代码位于它自己的程序集(OpenMon.MCE.ML)中
对每个战斗者,AI 会从其 Agent Prefab 生成一个 MCEAgent,写入一个观测向量(代码记录了 630 个整数:场景设定、双方的状态、四名上场战斗者以及其余队伍,每个战斗者由物种、形态、等级、个体值/努力值、特性、HP、状态、招式与 PP、携带道具、能力等级和易变状态描述),并向大脑请求离散的决策,再将其转换为 BattleAction。当怪物濒死时给予奖励(己方濒死时为 -10 的一部分,对手濒死时为 +100 的一部分)。濒死后派出哪只怪物不是通过学习得到的:它交给 Fallback。
训练 AI
训练在 Unity 之外进行,使用标准的 ML-Agents 工具链。MCE 提供的是智能体、观测与奖励;训练好的模型由你自己产出。
- 在虚拟环境中安装 Python 部分:
pip install mlagents - 按照 ML-Agents 配置参考, 为你的智能体预制件所声明的行为(behaviour)编写一份配置
- 运行
mlagents-learn <你的配置>.yaml --run-id=<名称>,当它提示等待时在 Unity 中按下 Play - 用
tensorboard --logdir results监控 - 导出训练好的模型(
.onnx文件) - 将模型分配给你的 agent 预制体
引擎自身的仓库在根文件夹中保留了这些步骤的封装脚本(MLAgentsInstall.ps1、RunMLTraining.ps1、
ViewMLResults.ps1 和 MLAgentsConfig/)。它们是维护者的工具,不包含在任何软件包中,
因此不在你收到的内容里:请按照上面的步骤操作。
ML-Agents 是一个独立的包,有自己的 Python 依赖。MCE 的核心战斗系统不需要它也能工作。只有在你计划使用基于神经网络的 AI 时才安装 ML-Agents。
AI 难度指南
| 难度 | AI 链 | 使用场景 |
|---|---|---|
| 非常简单 | 仅 RandomBattleAI | 野生遭遇 |
| 简单 | PerformRandomMove | 早期道路、新手 |
| 中等 | PerformEffectiveMove(感知属性) | 道馆训练师、劲敌 |
| 困难 | Mega + 道具 + 替换 + 有效招式 | 道馆馆主、四天王 |
| 神经网络 | 带训练模型的 MLBattleAI | 竞技、挑战模式 |
最佳实践
- 让 AI 匹配叙事背景。一个普通的捕虫少年不该像冠军那样战斗。
- 用相近等级的玩家队伍测试 AI。失衡的 AI 会让人觉得不公平。
- 用小型策略构建链。它们比一个庞大的整体 AI 更容易维护。
- 始终让链以
RandomBattleAI结尾(或由它兜底的PerformRandomMove),这样 AI 永远不会无从作答。 - 不要为早期训练师过度优化 AI。玩家需要先学会这个系统,才会面对聪明的对手。