遭遇与刷怪
This content is not available in your language yet.
大海图上划定若干“危险海域”(遭遇区),玩家船驶入后按该海域专属的时间线分波刷怪、保底补怪,驶离或沉船则全部清场——参考 Vampire Survivors 的“区域内临时竞技场”模型。
遭遇系统(Service.Encounter)负责回答三个问题:在哪刷怪、刷什么怪、什么时候刷。它是航海阶段的主要战斗内容来源,与 怪物、战利品与掉落、船只 共同构成“航行 → 遭遇 → 战斗 → 拾取”循环。
玩家视角的完整体验:
- 驾船航行,船的位置点进入某个遭遇区边界 → 屏幕顶部弹出浅黄色提示“进入海域 — {海域名}”(持续 3 秒)。
- 该海域的时间线开始走表:按预设秒数分波刷怪;压力地板保证场上活怪不低于保底数量。
- 怪物刷出后有 1.5 秒“登场期”——不可见、不可被攻击、不会撞船,之后才进入正常 AI。
- 玩家驶离遭遇区 → 中灰色提示“已离开 — {海域名}”(持续 2 秒),场上残余怪物全部走正常死亡流程(照常掉落,战利品留在原地)。
- 离开后该海域进入重入冷却(每区独立配置,30~180 秒),冷却内再进入不会重新开场。
- 玩家船沉没 → 所有活跃遭遇会话立即清场(怪物照常掉落),且不记录冷却——复活后再进同一海域立即重新开场。
系统在游戏启动时加载两张 CSV(EncounterBootstrap.cs):
Assets/StreamingAssets/Encounter/EncounterZones.csv—— 遭遇区定义(5 个区)Assets/StreamingAssets/Encounter/EncounterTimelines.csv—— 时间线定义(4 条共 20 行)
策划改这两张表即可调整全部遭遇内容,无需改代码。
遭遇区(EncounterZone)
Section titled “遭遇区(EncounterZone)”每个遭遇区是海面上的一块二维区域(俯视 XZ 平面),由 EncounterZones.csv 配置,EncounterZoneRegistry.cs 加载解析。
形状支持两种写法(同一列,前缀区分,EncounterCsvParser.cs):
| 写法 | 格式 | 说明 |
|---|---|---|
| 圆形 | circle:中心x,中心z,半径 |
三个数字,世界坐标,单位:格(米) |
| 多边形 | `polygon:x1,z1 | x2,z2 |
含逗号的形状字符串在 CSV 里需整列加英文双引号。格式写错、顶点不足 3 个、前缀未知的行会在加载时记日志并跳过,不影响其它行。
进出判定(ActiveZoneTracker.cs):每 0.1 秒(10 次/秒,按真实时间计)检测一次玩家船中心点是否落在各区内。圆形按“到圆心距离 ≤ 半径”,多边形按射线法点包含测试。进入/离开均广播全局事件,驱动会话开关与画面提示。判定的是船的单点位置,不考虑船体尺寸。
遭遇区全表(来源:CSV 配置表 EncounterZones.csv,共 5 行,全部为多边形):
| zoneId | 海域名 | 形状(世界坐标 XZ 顶点) | 大致范围 | tier | 时间线 | 重入冷却(秒) | 循环模式 |
|---|---|---|---|---|---|---|---|
| zone_east | 不列颠东海 | (2700,0) (3500,0) (3500,2500) (2700,2500) | 800×2500 矩形 | 1 | swarm_light | 30 | Once |
| zone_west | 伊比利亚远海 | (-2500,0) (-1700,0) (-1700,2500) (-2500,2500) | 800×2500 矩形 | 2 | swarm_med | 45 | Once |
| zone_central | 中央商船航道 | (-1100,1300) (1700,1300) (1700,2200) (-1100,2200) | 2800×900 矩形 | 2 | swarm_med | 45 | Once |
| zone_north | 法国海域 | (-700,3500) (1700,3500) (1700,4700) (-700,4700) | 2400×1200 矩形 | 3 | swarm_heavy | 60 | Loop |
| zone_south | 北海深渊 | (-1500,6000) (3500,6000) (3000,7000) (-1500,7000) | 约 5000×1000 梯形 | 4 | boss_kraken | 180 | Once |
tier(危险等级)对玩家不可见——画面提示与小地图均不按 tier 区分颜色(设计意图:让玩家自己记住哪片海危险)。tier 目前只用于编辑器 Scene 视图的色块(1 绿 / 2 黄 / 3 橙 / 4 红,EncounterZoneGizmoRenderer.cs),并随“进入海域”事件携带,供未来扩展。
小地图呈现(MiniMapPresenter.cs):已被发现的遭遇区在小地图上画统一的红色半透明区块(红 alpha=0.25,不按 tier 分色),未发现的区不显示。港口周围另画半径 80 格的青绿色“安全圈”,纯视觉提示,不影响任何刷怪逻辑(来源:代码常量 HarborSafeZoneConstants.cs,半径 80、颜色 RGBA(64,224,168,64))。
发现联动:首次成功开启某区的遭遇会话时,该区被标记为“已发现”(ArenaSessionManager.cs 调用发现注册表),之后才出现在小地图上。详见 探索与情报。
竞技场会话(ZoneArenaSession)
Section titled “竞技场会话(ZoneArenaSession)”会话是“一次进入遭遇区”的运行时实体(ZoneArenaSession.cs),由 ArenaSessionManager.cs 统一管理,规则:
- 一区一会话:进入区且通过重入冷却检查 → 新建会话;该区已有活跃会话则不重复建。
- 多区可并行:遭遇区允许重叠,船同时位于两个区内时两个会话同时运转、各刷各的(场景测试
ScenarioOverlapZones.cs验证此行为)。 - 离开即销毁:离开区 → 会话销毁,场上该会话的所有活怪强制走正常死亡(掉落留原地),并记录离开时刻供重入冷却计时。
- 沉船全清:玩家船沉没 → 所有会话立即销毁(怪照常死亡掉落),不记录离开时刻,因此复活后再进同区无冷却。
每个会话内部并联三套子机制,按不同频率驱动(计时使用游戏时间,受游戏速度倍率影响,见 时间与调度):
| 子机制 | 检查频率 | 职责 |
|---|---|---|
| 时间线执行器 TimelineRunner | 每帧 | 按秒数触发波次行 |
| 压力地板 PressureFloor | 3 次/秒 | 活怪数低于保底时补刷 |
| 强制消失 DespawnEnforcer | 2 次/秒 | 回收离船过远的怪 |
会话全程统计四个计数,会话结束时随事件广播(EncounterMessages.cs):总刷出数 TotalSpawned、被玩家击杀数 KilledByPlayer、距离过远回收数 DespawnedAtDistance、离场清理数 CleanedOnExit。
会话可整体暂停(开发者工具“暂停刷怪”):暂停时时间线、压力地板、强制消失三者同时停摆——既不刷新怪,也不会偷偷清场。
刷出的怪物会把所在遭遇区设为自己的游荡范围(EncounterZoneIdleZoneAdapter.cs):待机巡逻被约束在区边界内;但追击玩家可以越界,越界怪最终由“强制消失”规则按离船距离回收。
时间线(Timeline)
Section titled “时间线(Timeline)”时间线是一张“第几秒做什么”的波次表,EncounterTimelines.csv 每行四列:
| 列 | 含义 |
|---|---|
| timelineId | 时间线名,被遭遇区的 timelineId 列引用 |
| t | 触发时刻,单位:秒(小数可用),从会话开启起算(游戏时间) |
| action | 动作类型,见下 |
| payload | 动作参数,键=值;键=值 格式(分号分隔,不用 JSON) |
加载时按 t 升序排序;同一帧内凡是 t ≤ 已流逝秒数 的行全部依次触发(追帧安全,卡顿不会漏行)。t=0 的行在会话开启后的第一帧触发。
动作类型全解(EncounterActionType.cs + TimelineRunner.cs):
| 动作 | payload 字段 | 行为 | 状态 |
|---|---|---|---|
| SpawnMonster | type(怪物类型枚举名)、count(数量,缺省 1) |
立即按定向生成规则刷出 count 只怪 | 已实现 |
| SetPressureFloor | min(保底活怪数,必填)、fillType(补刷怪类型,缺省 Normal)、fillCount(每次补刷数量,缺省 1) |
改写压力地板状态,持续到下一次改写或时间线重置 | 已实现 |
| SpawnPirateShip | — | 占位,触发时记日志跳过 | 未实现 |
| TriggerWeather | — | 占位,触发时记日志跳过 | 未实现 |
| SpawnTreasureBoat | — | 占位,触发时记日志跳过 | 未实现 |
type 可填 MonsterType.cs 中的枚举名:Normal、Elite、Boss1、Boss2、SteelHorseshoe、BlazeSerpent、GlideRay、BarnacleSwarm、AbyssBeast。前提是该类型在 StaticMonsterConfig.csv 有数据行(当前 Boss2 没有行,填了会刷不出来并记错误日志)。各类型属性见 怪物。
循环模式(遭遇区级配置 loopMode,LoopMode.cs):
- Once:所有行触发完后时间线静默,进入“稳态”——只剩压力地板按最后一次设置的保底值持续补怪,直到玩家离开。
- Loop:所有行触发完后立即重置(计时归零、行指针归零),压力地板同时被清零,下一帧从
t=0重新走表。循环周期 = 最后一行的 t 值(如 swarm_heavy 为 60 秒一轮)。
时间线全表(来源:CSV 配置表 EncounterTimelines.csv,4 条共 20 行,全量收录):
swarm_light(不列颠东海,tier 1,Once)——总计 5 只 Normal:
| t(秒) | 动作 | 参数 |
|---|---|---|
| 0 | SetPressureFloor | min=1 |
| 0 | SpawnMonster | Normal × 2 |
| 12 | SpawnMonster | Normal × 3 |
| 30 | SetPressureFloor | min=2(稳态保底) |
swarm_med(伊比利亚远海 / 中央商船航道,tier 2,Once)——总计 12 只 Normal:
| t(秒) | 动作 | 参数 |
|---|---|---|
| 0 | SetPressureFloor | min=2 |
| 0 | SpawnMonster | Normal × 3 |
| 8 | SpawnMonster | Normal × 4 |
| 20 | SpawnMonster | Normal × 5 |
| 40 | SetPressureFloor | min=4(稳态保底) |
swarm_heavy(法国海域,tier 3,Loop,60 秒一轮)——每轮 18 只 Normal + 1 只 Elite:
| t(秒) | 动作 | 参数 |
|---|---|---|
| 0 | SetPressureFloor | min=3 |
| 0 | SpawnMonster | Normal × 4 |
| 6 | SpawnMonster | Normal × 6 |
| 18 | SpawnMonster | Elite × 1 |
| 35 | SpawnMonster | Normal × 8 |
| 60 | SetPressureFloor | min=6(Loop 模式下此行实际无效,见已知限制) |
boss_kraken(北海深渊,tier 4,Once)——总计 10 只 Normal + 1 只 Boss1:
| t(秒) | 动作 | 参数 |
|---|---|---|
| 0 | SetPressureFloor | min=4 |
| 0 | SpawnMonster | Normal × 4 |
| 20 | SpawnMonster | Boss1 × 1 |
| 45 | SpawnMonster | Normal × 6 |
| 90 | SetPressureFloor | min=8(稳态保底) |
压力地板(PressureFloor,保底刷怪)
Section titled “压力地板(PressureFloor,保底刷怪)”压力地板保证“区里永远有怪打”,防止玩家清完场后干等下一波(PressureFloor.cs)。
触发规则(伪公式):
每 1/3 秒检查一次: 若 保底值 min > 0 且 场上该会话活怪数 < min 且 距上次强制补刷 ≥ 3 秒(ForcedSpawnCooldown)→ 补刷 fillType × fillCount(默认 Normal × 1)要点:
- 默认保底为 0(永不补刷)。想要“一进区就有保底压力”,必须在时间线
t=0显式写一行 SetPressureFloor。当前 4 条时间线都遵守这个习惯。 - 补刷不是一次补满缺口:每满 3 秒冷却补一批 fillCount 只。默认配置下补怪速率约为每 3 秒 1 只。
- 活怪数 等于 min 时不触发(判定是“小于”)。
- 3 秒冷却是会话内共享计时,跨 Loop 重置仍然有效。
- 冷却时长 3 秒为代码常量(
EncounterSpawnConstants.cs的 ForcedSpawnCooldown,改它需要程序改代码)。 - 当前 CSV 只用到
min字段;fillType/fillCount是 SetPressureFloor 的可选参数,想让保底刷精英(如min=2;fillType=Elite;fillCount=2)直接写进 payload 即可,解析已支持(TimelineRunner.cs)。
定向生成(DirectionalSpawnDirector,从哪个方向刷)
Section titled “定向生成(DirectionalSpawnDirector,从哪个方向刷)”所有刷怪请求(时间线波次、压力地板补刷、开发者工具强制刷怪)统一走同一套位置采样(DirectionalSpawnDirector.cs)。核心思想:以船为基准的非对称矩形——前方刷得远、后方刷得近、两侧适中,确保怪出现在玩家航向前方的可见区域,而不是船尾追不上的尾流里。
每只怪独立采样,单只最多尝试 20 次,每次按顺序过 6 道关:
1. 在船本地坐标矩形内随机取点: 横向 x ∈ [-35, +35] 格(右舷为正) 纵向 z ∈ [-10, +50] 格(船头为正:前方最远 50,后方最多 10)2. 距船 < 20 格(InnerSafe 内圈)→ 拒绝(防贴脸刷)3. 转世界坐标,高度固定为海面 y=04. 不在本遭遇区边界内 → 拒绝(保证怪刷在区里)5. 落在陆地(任一岛屿多边形内)→ 拒绝(LandWanderFilter)6. 与本批已选点距离 < 该怪种的"怪物间最小距离" → 拒绝(防扎堆)20 次都失败则放弃该只(整批结束记一条日志),所以实际刷出数可能少于请求数——典型场景是船贴着区边缘或区被陆地大量占据时。
由此可知怪的出生距离恒在 20 ~ 61 格之间(矩形对角最远 √(35²+50²)≈61),且伴随船头朝向旋转。矩形四个尺寸与内圈半径均为代码常量(EncounterSpawnConstants.cs)。
第 6 步的“怪物间最小距离”读自怪物配置表(来源:CSV 配置表 StaticMonsterConfig.csv 的 MinDistanceBetweenMonsters 列;类型缺数据时代码兜底 2 格):
| 怪物类型 | 最小间距(格) |
|---|---|
| Normal / Elite / SteelHorseshoe / BlazeSerpent / GlideRay | 2 |
| BarnacleSwarm(藤壶群,密集小体设计) | 1 |
| Boss1 / AbyssBeast | 3 |
登场保护(fade-in):怪刷出后立刻进入 Spawning 状态(SpawningState.cs,时长 1.5 秒,代码常量):碰撞体关闭、模型整体隐藏、不可被攻击、不可被锁定、自身索敌也被抑制。1.5 秒后切回正常待机,AI 接管。这同时解决“刷出瞬间被玩家秒杀”和“刚出现就撞船”两个问题。注意视觉上是整体隐藏后突然出现,不是渐变透明(URP 不透明材质无法做透明度渐变)。
强制消失(Despawn)
Section titled “强制消失(Despawn)”每 0.5 秒(2 次/秒)检查会话内每只活怪与玩家船的直线距离,超过 100 格即强制回收(DespawnEnforcer.cs,距离阈值为代码常量 EncounterSpawnConstants.cs 的 DespawnRange)。
关键设计:回收不是直接删除,而是调用与被玩家打死完全相同的死亡入口——怪走完整死亡流程、照常掉落战利品,掉落物留在怪消失的位置。漂在远海的战利品玩家想要就得折返去捡,这是有意的设计后果(“打死就要掉,不要特殊处理”)。离区清场、沉船清场同理,三条死亡路径只有统计计数不同。掉落规则详见 战利品与掉落。
重入冷却(Reentry Cooldown)
Section titled “重入冷却(Reentry Cooldown)”每个遭遇区独立配置冷却秒数(CSV reentryCooldown 列)。计时从离开该区的时刻起算(游戏时间);冷却未满时再次进入:
- 不会新建会话——区内安静无怪;
- 但“进入海域”画面提示仍会弹出(进入事件照发,只是会话管理器忽略它)。
冷却满后再进入则正常重新开场、时间线从头走。当前配置:tier 1 区 30 秒、tier 2 区 45 秒、tier 3 区 60 秒、Boss 区 180 秒。
| 项目 | 数值 | 单位 | 来源 |
|---|---|---|---|
| 遭遇区进出检测频率 | 每 0.1 秒一次(10 Hz,真实时间) | 秒 | 代码常量 ActiveZoneTracker.cs |
| 时间线推进 | 每帧累加游戏时间 | — | TimelineRunner.cs |
| 压力地板检查频率 | 每 1/3 秒一次(3 Hz) | 秒 | 代码常量 ZoneArenaSession.cs |
| 强制消失检查频率 | 每 0.5 秒一次(2 Hz) | 秒 | 代码常量 ZoneArenaSession.cs |
| 压力地板补刷冷却 | 3 | 秒 | 代码常量 EncounterSpawnConstants.cs |
| 压力地板默认补刷 | Normal × 1 | — | 代码默认值 PressureFloor.cs |
| 刷怪矩形:船前方最远 | 50 | 格 | 代码常量 EncounterSpawnConstants.cs |
| 刷怪矩形:船后方最远 | 10 | 格 | 代码常量 EncounterSpawnConstants.cs |
| 刷怪矩形:两侧最远 | 35 | 格 | 代码常量 EncounterSpawnConstants.cs |
| 贴脸保护内圈半径 | 20 | 格 | 代码常量 EncounterSpawnConstants.cs |
| 出生点距船范围(推导值) | 20 ~ 约 61 | 格 | 由上四项推出 |
| 单只采样尝试上限 | 20 | 次 | 代码常量 EncounterSpawnConstants.cs |
| 登场保护时长 | 1.5 | 秒 | 代码常量 SpawningState.cs(与 EncounterSpawnConstants.cs 同值同步维护) |
| 强制消失距离 | 100(距玩家船) | 格 | 代码常量 EncounterSpawnConstants.cs |
| 重入冷却 | 30 / 45 / 60 / 180(按区) | 秒 | CSV 配置表 EncounterZones.csv |
| 怪物间最小出生距离 | 1 / 2 / 3(按怪种) | 格 | CSV 配置表 StaticMonsterConfig.csv |
| “进入海域”提示时长 | 3 | 秒 | 代码常量 ZoneToastPresenter.cs |
| “已离开”提示时长 | 2 | 秒 | 代码常量 ZoneToastPresenter.cs |
| 小地图危险区颜色 | 红,透明度 0.25,统一不分 tier | — | 代码常量 MiniMapPresenter.cs |
| 港口安全圈 | 半径 80 格,青绿色,纯视觉 | 格 | 代码常量 HarborSafeZoneConstants.cs |
| 开发用区外刷怪虚拟区半径 | 100000 | 格 | 代码常量 ArenaSessionManager.cs |
时间口径说明:除“遭遇区进出检测”用真实时间外,时间线推进、压力地板冷却、重入冷却、强制消失计时均使用游戏时间——游戏加速/暂停会同比影响波次节奏与冷却。
与其他系统的交互
Section titled “与其他系统的交互”- 怪物:刷怪最终调用怪物工厂按
StaticMonsterConfig.csv数据生成实例;时间线type字段必须是该表已有的怪种。刷出的怪以所在遭遇区为游荡范围(待机不出区,追击可出区)。 - 战利品与掉落:被玩家打死、离船超 100 格回收、离区/沉船清场,三种死法都走同一掉落流程,掉落物留在死亡位置。
- 船只:玩家船位置驱动进出判定与刷怪几何;船沉没事件触发全会话清场(无重入冷却记录),复活流程由船只系统负责。
- 探索与情报:首次在某区开启会话即标记该区“已发现”;小地图只渲染已发现的危险区。
- 元素与状态效果 / 伤害与护甲:遭遇系统只负责“把怪放进场”,战斗结算全部由战斗系统处理;登场保护期通过“不可被攻击/不可被锁定”开关实现。
- 时间与调度:时间线与各冷却按游戏时间走,受游戏速度控制。
- 存档:会话状态不存档。读档后按船当前位置重新判定、重新开场(设计决定:存档大概率发生在港口安全区)。
- 开发者工具:见下文调试小节。
- 界面总览:进/出提示为屏幕顶部居中 toast;小地图危险区/安全圈叠加层。
配置与调参指南
Section titled “配置与调参指南”| 想调什么 | 改哪里 |
|---|---|
| 某片海域的位置/大小/形状 | EncounterZones.csv 的 shape 列(circle 或 polygon 写法) |
| 某片海域打哪条波次表 | EncounterZones.csv 的 timelineId 列 |
| 离开后多久能再刷 | EncounterZones.csv 的 reentryCooldown 列(秒) |
| 波次打完是停在稳态还是循环 | EncounterZones.csv 的 loopMode 列(Once / Loop) |
| 第几秒刷什么怪刷几只 | EncounterTimelines.csv 加/改 SpawnMonster 行(t 秒 + type + count) |
| 区内保底活怪数量与补刷内容 | EncounterTimelines.csv 的 SetPressureFloor 行(min,可选 fillType / fillCount) |
| 新增一片海域 | EncounterZones.csv 加一行 + (可选)EncounterTimelines.csv 加一组行;zoneId / timelineId 不得与现有重复 |
| 怪的血量/速度/掉落/出生间距 | StaticMonsterConfig.csv(见 怪物) |
| 刷怪方向偏好(前/后/侧距离)、贴脸内圈、消失距离、补刷冷却 | 需程序改 EncounterSpawnConstants.cs 代码常量 |
| 登场保护时长 | 需程序改 SpawningState.cs(注意与 EncounterSpawnConstants.cs 同值,两处需同步) |
| 进/出提示文案与时长 | 需程序改 ZoneToastPresenter.cs |
| 港口安全圈半径/颜色 | 需程序改 HarborSafeZoneConstants.cs |
改完 CSV 后的校验工具:Unity 菜单 Tools → Encounter → Validate Configs(EncounterValidateMenu.cs)——重新加载两张表,列出每个区及其时间线,时间线 ID 找不到时给出警告(注意:运行时加载不做这项校验,写错只会让该区安静无怪,务必发布前跑一次)。
Scene 视图可视化:菜单 Tools → Encounter → Toggle Scene Gizmos 开关区块绘制(EncounterZoneGizmoRenderer.cs)——按 tier 着色(1 绿 / 2 黄 / 3 橙 / 4 红),有活跃会话的区描青色边框并在区中心浮动显示“alive=活怪数 total=总刷出数”。仅编辑器可见。
调试窗口与开发者工具
Section titled “调试窗口与开发者工具”Encounter Debug 窗口(EncounterDebugWindow.cs,仅编辑器 / 开发版构建,随系统自动出现在屏幕左侧,可拖动):
- 显示当前活跃会话列表:每条为“[zoneId] alive=活怪 total=总刷出 paused=是否暂停“。
- 按钮:Force Spawn Normal x3 / Force Spawn Elite x1(向当前第一个活跃会话强制刷怪,走完整定向生成流程)、Clear All Active Monsters(全场怪走正常死亡)、Pause Spawning / Resume Spawning(暂停/恢复所有会话的时间线+保底+消失检查)。
DevTools 面板对接(DevToolsManager.cs,详见 开发者工具):
- 强制刷怪:可选任意怪物类型与数量,路由到当前活跃会话。
- 清除所有怪 / 暂停恢复刷怪:与调试窗口同一套接口。
- 区外刷怪(ambient):在玩家船当前位置开一个半径 100000 格的虚拟会话(无时间线、不自动刷),让强制刷怪/清场在任何海面都可用;刷出的怪仍按“距船 100 格”规则回收,关闭时连带清掉该会话刷出的怪。
- 一键战斗测试布置:开武器开发模式 + 区外刷怪 + 挂全船武器操控 + 刷出五种代表性怪(钢壳鲎×2、炽鳞蛇×2、游曳鳐×2、藤壶群×6、渊海兽×1)。
另有六个端到端场景测试覆盖本系统(Service/DevTools/ScenarioTests/Encounter/):区内刷怪几何、时间线完整播放、Loop 循环、离区清场掉落守恒、重叠区双会话、登场保护期免伤。
已知限制与注意事项
Section titled “已知限制与注意事项”- 三种动作未实现:SpawnPirateShip(海盗船)、TriggerWeather(天气)、SpawnTreasureBoat(宝船)只是枚举占位,时间线里写了会被记日志跳过(
TimelineRunner.cs)。 - Loop 模式下把 SetPressureFloor 放在最后一行无效:循环重置发生在最后一行触发后的同一次更新内,并立即把保底清零,下一轮由
t=0行重新设置。当前swarm_heavy的t=60 SetPressureFloor min=6行因此从未生效(法国海域实际保底始终是 3)。单元测试TimelineRunnerTests.cs明确锁定了这个清零行为;想给 Loop 区抬保底,应改t=0那行的 min 值。 - 同一 t 的多行触发顺序不严格保证:加载时按 t 排序使用的算法对相等 t 值不保证保持 CSV 原顺序(
EncounterTimelineRegistry.cs)。当前每条时间线行数少,实际表现与 CSV 顺序一致,但设计文档承诺的“按 CSV 出现顺序”在代码层面没有硬保证;同一 t 的行之间不要写有先后依赖的逻辑。 - 运行时不校验 timelineId 引用:zone 指向不存在的时间线时照常加载,会话开起来但永远不刷怪(空表 + 保底 0)。只有手动跑 Validate Configs 菜单才能发现。
- 冷却期间提示照弹:重入冷却内进区不开场,但“进入海域”toast 仍会出现,玩家可能误以为有怪。
- 沉船不记冷却:沉没清场不写离开时刻,复活后立刻重进可立即重新开场——与正常离开的行为不对称(当前实现如此)。
- 刷怪数量不保证:采样 20 次失败即放弃该只,区太小、船贴边、陆地占比高时实际刷出会少于配置值,只记日志不补偿。
- 登场视觉是“隐藏 1.5 秒后突现”:设计稿写的透明度 0→1 渐变因 URP 不透明材质无法实现,退化为整体隐藏(
SpawningState.cs注释明确此取舍);也没有出生水花/烟雾特效(代码中留有待办注释)。 - 调试窗口比设计稿精简:设计稿承诺的“显示下一事件 / Skip to next event / End session / Reset session”未实现,当前只有强制刷怪/清场/暂停恢复;Scene gizmo 也未实现设计稿中的“登场期怪青圈、正常怪红圈、floor 值显示”。
- 强制刷怪只作用于“第一个”会话:多会话并行时,调试强制刷怪固定取内部列表第一个会话,不可选目标区。
- 会话状态不存档:航行中存档再读档,波次进度、已刷怪、冷却记录全部丢失,按位置重新开场。
- 进出判定是船中心单点:大船船身压线但中心点未入区时不触发;进出抖动由 0.1 秒检测间隔与区边界几何决定,无迟滞缓冲。
- 系统初始化挂在场景加载后并轮询等待玩家船就绪(
EncounterBootstrap.cs)——极端情况下玩家船永不出现则整个系统静默不启动,仅影响开发期特殊场景。