战斗 AI
MCE 使用可插拔的策略模式来实现战斗 AI。AI 系统基于 BattleAI 基类和一系列 BattleAction 组件构建,可以组合它们来创建不同的难度级别和行为风格。
架构
AI 管线分为两层:
- BattleAI -- 接收当前战斗状态并返回
BattleAction的入口点。 - BattleAction 组件 -- 独立的决策单元,评估战斗的某一方面(例如"我应该使用效果拔群的招式吗?"或"我应该切换到抗性怪兽吗?")。
一个 BattleAI 实例持有一个有序的 BattleAction 组件列表。它按优先级顺序评估它们,第一个产生有效行动的组件获胜。
内置 AI 策略
MCE 附带多种可混合搭配的 AI 策略:
RandomBattleAI
最简单的 AI。每回合随机选择一个有效招式。
- 难度:非常简单
- 使用场景:野生遭遇、前期训练师
- 行为:从可用招式中随机选择。没有策略思考。
PerformEffectiveMove
选择对当前目标造成最有效伤害的招式。
- 难度:中等
- 使用场景:中期训练师、道馆馆主
- 行为:计算每个可用招式的属性克制并选择最佳招式。不考虑能力值变化或变化招式。
PerformRandomMove
类似于 RandomBattleAI 但带有加权招式选择。
- 难度:简单
- 使用场景:低等级训练师
- 行为:随机选择招式,略微偏好伤害招式而非变化招式。
内置行动组件
这些组件可以组合成自定义 AI 策略:
| 组件 | 描述 |
|---|---|
PerformEffectiveMove | 使用属性克制最佳的招式 |
PerformRandomMove | 使用随机招式 |
MegaOrGigaIfCan | 如果可以则激活 Mega 进 化或极巨化 |
SwitchToEffectiveMonster | 切换到具有属性优势的队伍成员 |
UseBattleItems | HP 低时使用治疗或状态道具 |
IfWildWithRunChanceRun | 野生怪兽可能尝试逃跑 |
为每个训练师配置 AI
每个训练师 NPC 可以有不同的 AI 配置:
- 在训练师的
Actor或遭遇数据上,找到 AI Configuration 字段。 - 分配一个
BattleAIScriptableObject。 - 配置行动组件列表及其优先级顺序。
配置示例:
简单训练师(路线 1)
1. PerformRandomMove
中等训练师(道馆谜题)
1. MegaOrGigaIfCan
2. PerformEffectiveMove
3. PerformRandomMove(备选)
困难训练师(冠军)
1. MegaOrGigaIfCan
2. SwitchToEffectiveMonster(处于劣势时)
3. UseBattleItems(HP < 25% 时)
4. PerformEffectiveMove
5. PerformRandomMove(备选)
IBattleAI 接口
对于 DLL 版本用户,AI 系统通过 BattleAI 基类访问。虽然没有源代码无法修改内部实现,但你可以:
- 在编辑器中创建新的
BattleAIScriptableObject。 - 通过 Inspector 配置行动组件列表。
- 将它们分配给训练师。
关键接口:
public abstract class BattleAI : ScriptableObject
{
// 按顺序评估的 BattleAction 组件列表
public List<BattleAction> Actions;
}
public abstract class BattleAction : ScriptableObject
{
// 评估是否应该执行此行动
// 如果此行动不适用则返回 null
public abstract BattleActionResult Evaluate(BattleContext context);
}
ML-Agents 集成
MCE 包含实验性的基于 ML-Agents 的 AI,用于高级难度:
MLBattleAI
使用 Unity ML-Agents 基于训练好的神经网络做出决策。
- 难度:可变(取决于训练)
- 使用场景:终盘训练师、竞技 AI、研究
- 设置:需要 ML-Agents 包和训练好的模型
训练 AI
- 安装 ML-Agents 依赖:
.\MLAgentsInstall.ps1 - 在
MLAgentsConfig/OpenMonAgent.yaml中配置训练参数 - 开始训练:
.\RunMLTraining.ps1 - 使用 TensorBoard 监控:
.\ViewMLResults.ps1 - 导出训练好的模型(
.onnx文件) - 将模型分配给
MLBattleAI组件
MCEBattleAgent 类定义了观察空间和动作空间:
观察(AI 看到的内容):
- 自身怪兽的 HP 百分比、属性、能力值等级、状态异常。
- 对手怪兽的 HP 百分比、属性、能力值等级、状态异常。
- 可用招式及其属性。
- 队伍状态(剩余怪兽、HP 百分比)。
动作(AI 可以执行的操作):
- 使用招式 1-4。
- 切换到队伍成员 1-5。
- 使用道具。
ML-Agents 依赖
ML-Agents 是一个独立的包,有其自己的 Python 依赖。核心 MCE 战斗系统不需要它即可工作。只有在计划使用基于神经网络的 AI 时才安装 ML-Agents。
创建自定义 AI(Source 版本)
拥有源代码访问权限后,你可以创建全新的 AI 策略:
自定义 BattleAction
[CreateAssetMenu(menuName = "OpenMon/AI/Actions/Use Status Move If No Status")]
public class UseStatusMoveIfNoStatus : BattleAction
{
public override BattleActionResult Evaluate(BattleContext context)
{
// 检查对手是否没有状态异常
if (context.OpponentBattler.StatusCondition != StatusCondition.None)
return null; // 跳过此行动
// 寻找一个施加状态的招式
foreach (var moveSlot in context.OwnBattler.MoveSlots)
{
if (moveSlot.Move.Category == MoveCategory.Status
&& moveSlot.CurrentPP > 0
&& moveSlot.Move.InflictsStatus)
{
return new BattleActionResult
{
ActionType = BattleActionType.UseMove,
MoveIndex = moveSlot.Index
};
}
}
return null; // 没有找到适用的状态招式
}
}
自定义 BattleAI
[CreateAssetMenu(menuName = "OpenMon/AI/Strategies/Expert AI")]
public class ExpertBattleAI : BattleAI
{
// 如果需要可以覆盖决策管线
public override BattleActionResult DecideAction(BattleContext context)
{
// 超越简单行动组合的自定义逻辑
// 例如前瞻预测、队伍协同分析
return base.DecideAction(context);
}
}
AI 难度指南
| 难度 | AI 组件 | 使用场景 |
|---|---|---|
| 非常简单 | 仅随机招式 | 野生遭遇 |
| 简单 | 加权随机招式 | 早期路线、初级训练师 |
| 中等 | 属性克制感知 | 道馆训练师、对手 |
| 困难 | 克制 + 切换 + 道具 | 道馆馆主、四天王 |
| 专家 | 完整组合 + 预测 | 冠军、通关后内容 |
| 神经网络 | ML 训练模型 | 竞技、挑战模式 |
最佳实践
- 将 AI 与叙事场景匹配。一个随机的虫系捕手不应该像冠军一样战斗。
- 用相似等级的玩家队伍测试 AI。不平衡的 AI 让人感觉不公平。
- 使用行动组件模式。它比单体 AI 脚本更易于维护。
- 提供备选方案。始终将
PerformRandomMove作为最后一个行动,以防止 AI 卡住。 - 不要对早期训练师过度优化 AI。玩家需要在面对聪明对手之前学习系统。