战斗启动
一个场景固定运行一场遭遇战时使用 Bootstrap;地图、任务或关卡流程需要动态选择遭遇战时,调用 GCSApi.StartBattle,并通过生命周期事件把控制权交回自己的游戏逻辑
当 GCS 战斗只是完整游戏循环中的一个环节,而不是整个场景的全部内容时GameCardManager 负责让内容可用,什么时候开战则是另一件事:先选出 GameEncounter,再决定何时启动,以及胜利或失败之后游戏回到哪里
选择启动方式
- 一个场景一场遭遇战
- 地图或流程控制
进入 Play Mode 后总是运行一场固定遭遇战时,使用 GameCardEncounterBootstrap。Demo、独立战斗测试,以及专门为某场遭遇战加载的战斗场景都适合这种方式
关闭自动启动,由地图、任务、分支流程或匹配结果选出遭遇战,再调用 GCSApi.StartBattle(encounter)。这也是正式游戏更常见的接入方式
使用 GameCardEncounterBootstrap 自动启动
GameCardEncounterBootstrap 与 GameCardManager 挂在同一个 GameObject 上。它的字段只控制自动启动这条路径:
| 字段 | 默认值 | 作用 |
|---|---|---|
Default Encounter | 新组件为空 | 自动启动时传给 GameCardManager.StartBattle 的遭遇战 |
Auto Start On Play | 开启 | 在 Start 中启动 Default Encounter;由其他系统选遭遇战时应关闭 |
Use GES Events | 关闭 | 决定战斗启动后调用 UnityEvent,还是触发已配置的 GES 事件 |
On Bootstrap | 空 | Use GES Events 关闭时,在 Bootstrap 调用 StartBattle 后触发 |
On Bootstrap Events | 空 | Use GES Events 开启时,在 StartBattle 后按列表顺序触发 |

Inspector 会检查 Default Encounter 是否位于启用的遭遇战数据库中。状态显示 Ready,说明选择和数据库登记一致。自动启动已开启但字段为空时,Play Mode 只会记录警告,不会启动战斗
Bootstrap 上的 UnityEvent 和 GES 列表是这个组件的启动后输出。代码直接调用 GCSApi.StartBattle 时不会触发它们,因此地图或关卡流程不能只依赖这些字段监听战斗生命周期
不使用 Bootstrap 启动遭遇战
场景仍然保留 GameCardManager,将 Auto Start On Play 关闭,再把选中的遭遇战交给公开 API:
using TinyGiants.GCS.Runtime;
using UnityEngine;
public sealed class EncounterLauncher : MonoBehaviour
{
[SerializeField] private GameEncounter encounter;
public void StartConfiguredEncounter()
{
if (encounter == null) return;
GCSApi.StartBattle(encounter);
}
public void StartEncounter(GameEncounter selectedEncounter)
{
if (selectedEncounter == null) return;
GCSApi.StartBattle(selectedEncounter);
}
}
地图节点、UI 按钮、任务系统或你自己的 GES 事件处理器都可以调用这两个公开方法。GCSEventNames 里没有一个内置的“开始遭遇战事件”:GCSApi.StartBattle 是启动命令,战斗生命周期事件则是启动之后发出的通知
直接启动仍要求 Manager 启用的卡牌、状态、敌人、玩家和卡组数据库覆盖这场遭遇战引用的内容。把遭遇战本身也放在启用的遭遇战数据库中,可以保证它继续出现在工作台、选择器和 GCSApi.Encounters() 的查询结果里
监听战斗开始与结束
必须先订阅,再调用 StartBattle。OnBattleStarted 会在创建战斗状态的过程中同步发出,启动之后才订阅会错过这一场战斗
| 事件 | 参数 | 准确时机 |
|---|---|---|
GCSEventNames.OnBattleStarted | 无 | 玩家、敌人、初始牌库和起手手牌已经创建;随后解析敌人意图,并进入第一个玩家回合 |
GCSEventNames.OnBattleRewardOffered | BattleRewardOfferedEventArgs | 已判定胜利,GCS 正在等待玩家选择或跳过奖励 |
GCSEventNames.OnBattleEnded | BattleEndedEventArgs | 失败时立即发出,Won == false;胜利时要等奖励被选择或跳过后才发出,Won == true |
GCSApi.Subscribe 返回 IDisposable。保存订阅句柄,并在监听对象禁用或销毁时调用 Dispose
完整的地图到战斗循环
把下面的协调器和 GameCardManager 放在始终保持激活的对象上,MapRoot 和 BattleRoot 只是它控制的子对象,BattleRoot 只承载表现对象,不包含 Manager。协调器会先激活战斗表现,再调用 StartBattle,这样各个 Presenter 能在 OnBattleStarted 发出前完成订阅
using System;
using TinyGiants.GCS.Runtime;
using UnityEngine;
public sealed class MapEncounterFlow : MonoBehaviour
{
[SerializeField] private GameObject mapRoot;
[SerializeField] private GameObject battleRoot;
public event Action<GameEncounter> EncounterStarted;
public event Action<GameEncounter, bool> EncounterFinished;
private IDisposable battleStartedSubscription;
private IDisposable battleEndedSubscription;
private GameEncounter activeEncounter;
private void OnEnable()
{
battleStartedSubscription = GCSApi.Subscribe(
GCSEventNames.OnBattleStarted,
OnBattleStarted);
battleEndedSubscription = GCSApi.Subscribe<BattleEndedEventArgs>(
GCSEventNames.OnBattleEnded,
OnBattleEnded);
}
private void OnDisable()
{
battleStartedSubscription?.Dispose();
battleStartedSubscription = null;
battleEndedSubscription?.Dispose();
battleEndedSubscription = null;
}
public void StartMapEncounter(GameEncounter encounter)
{
if (encounter == null || GCSApi.Manager == null) return;
activeEncounter = encounter;
battleRoot.SetActive(true);
mapRoot.SetActive(false);
GCSApi.StartBattle(encounter);
}
private void OnBattleStarted()
{
EncounterStarted?.Invoke(activeEncounter);
}
private void OnBattleEnded(BattleEndedEventArgs args)
{
battleRoot.SetActive(false);
mapRoot.SetActive(true);
EncounterFinished?.Invoke(activeEncounter, args.Won);
activeEncounter = null;
}
}
转场或统计系统可以订阅 EncounterStarted,存档、地图节点、奖励或进度系统则订阅 EncounterFinished。边界很清楚:GCS 负责这一场战斗,你的协调器负责战斗前后的完整游戏流程
玩家放弃尚未结束的战斗,或提前离开战斗场景时,先调用 GCSApi.DisposeBattle()。这个调用只清理当前战斗,不会发出 OnBattleEnded,取消战斗后的地图处理需要由你的代码完成
进入 Play Mode 前检查
- 场景中只有一个
GameCardManager,并启用了这场战斗需要的数据库 - 自动启动:已指定
Default Encounter,并开启Auto Start On Play - 流程控制:关闭
Auto Start On Play,由协调器调用GCSApi.StartBattle - 生命周期订阅早于启动调用,并在对象禁用时释放
- 胜利流程完成奖励选择或跳过后,再等待
OnBattleEnded