HappyOyster 1.0 里把开放世界切到多细,先看实时生成从触发到可见要多久。更稳的顺序是反过来:先用同一份输入测一轮延迟,用测量结果决定颗粒度,而不是先定细颗粒度、再回头解释为什么卡。测量本身不难,难的是把对象数量、状态更新频率、生成区域大小拆开,让每次调整只动一个变量。
适用场景是单机或小规模联机的实时生成内容。操作动作:固定一份输入,记录触发到画面可见的耗时,重复多轮,记分布不记最好那次。验证方式是看延迟分布和异常样本比例,判断哪一档能稳定落在可接受范围内。边界:HappyOyster 1.0 各版本暴露的字段与行为可能不同,字段名以本地版本为准;测出的阈值只对当前机器、当前配置、当前内容规模成立,换环境要重测。
定义场景颗粒度的三个可观测维度
颗粒度不等于画面细节,它是三个能被日志记下来的维度。三者混在一起调,测完也说不清是谁在拖时间。
| 维度 | 低 | 中 | 高 |
|---|---|---|---|
| 对象数量 | 单个可交互对象或少量道具 | 一个小区域内多类对象共存 | 大量对象同时参与生成与交互 |
| 状态更新频率 | 仅在玩家操作后更新 | 按固定节奏更新位置与朝向 | 多路状态高频刷新 |
| 生成区域大小 | 镜头前方一小块 | 一个房间或一段街区 | 跨地形连续生成 |
表里的低中高只是示例,具体数量级由你自己填进测量表。判断方向是:对象数量影响单次生成量,状态更新频率影响单位时间内的触发次数,生成区域大小影响单次要覆盖的范围。升档时一次只动一个维度,另外两个保持不变,否则测出来的延迟无法归因。
设计一轮延迟测量
先固定一份输入:同一张地图、同一套参数、同一个起始位置。测量前跑一轮热身,把首次加载、编译这类一次性开销排除在正式样本之外。
记录字段建议至少包含下面几项,字段名可以替换成你本地日志里已有的名字:
| 字段 | 含义 | 怎么取 |
|---|---|---|
| trigger_ts | 触发时间 | 请求或调用发出的时刻 |
| visible_ts | 可见时间 | 结果首次出现在画面上的时刻 |
| latency_ms | 耗时 | visible_ts 减 trigger_ts |
| state_len | 状态长度 | 本次返回的状态体大小 |
| object_count | 对象数 | 本次参与生成的对象数量 |
| tier | 档位 | 本次跑的是哪一档颗粒度 |
| retry / note | 异常标记 | 重试、超时、返回空、画面停滞 |
每次触发写一行,追加到同一个文件里,测完再统一统计。一个可替换的记录骨架长这样:
tier,trigger_ts,visible_ts,latency_ms,state_len,object_count,retry,note
low,1690000000.120,1690000000.420,300,1200,3,0,
mid,1690000001.500,1690000002.900,1400,8400,12,0,
mid,1690000004.100,1690000007.600,3500,8400,12,1,timeout_retry
重复次数不要只跑一两次。建议每档至少跑够能看出波动的轮数,具体次数由你的时间预算决定;看中位数和最大值,不要只看平均值。凡是重试、超时、返回空、画面卡住的样本,单独标记后剔除,不要混进正常分布里当普通数据用。
按延迟区间给颗粒度分级
拿到分布以后,先给自己定两个阈值:A 是你能接受的单次等待上限,B 是超过 A 但仍能通过降级勉强接住的位置。这两个数由你的实测结果和玩家体验容忍度决定,不要照抄别人的配置。
| 档位 | 判据 | 处理动作 |
|---|---|---|
| 可实时 | 延迟中位数与最大值都落在阈值 A 以内,异常样本很少 | 保持当前颗粒度直接生成 |
| 可降级 | 延迟靠近 A,部分样本越过 A 但未超 B | 减对象数、拉长更新间隔或缩小生成区域,让它落回 A 以内 |
| 应预生成 | 延迟稳定超过 B,或异常样本频繁出现 | 这类场景不再走实时链路,改为提前准备内容 |
分级结果要跟着硬件和内容规模走。同一档在开发机上可实时,换到目标机型上可能就落到可降级,所以阈值和分级都要在目标环境里重新跑一遍再填。
用同一场景做升档和降档验证
分级只是一张静态快照,还要用同一个场景来回切一次,确认边界真实存在。升档验证的做法是:从当前档位往上调一个维度,另外两个维度保持不变,跑同样轮数,记录延迟和是否出现异常。降档验证反向做:往下调一个维度,确认延迟回落,同时判断画面是否还能看。
- 升档操作:增加同屏对象数量
- 升档操作:提高状态更新频率
- 升档操作:扩大生成区域
- 降档操作:减少参与生成的对象
- 降档操作:拉长状态刷新的间隔
- 降档操作:缩小生成区域到镜头附近
每档记一行,主观可玩性用统一口径判断:连续玩几分钟,是否出现明显等待、操作与画面脱节、生成内容突然空缺。
| 档位 | 改动的维度 | 延迟中位数 | 延迟最大值 | 主观可玩性 | 是否回退 |
|---|---|---|---|---|---|
| 基准档 | 无 | ||||
| 升一档 | |||||
| 降一档 |
如果升一档后延迟越界,说明该维度在当前配置下已经到头;如果降一档后延迟没有明显回落,说明瓶颈可能不在这一维度,换一个维度再试一次。
输出颗粒度选择建议
推荐起点是偏粗的一档:对象少、更新频率低、生成区域小,先保证整局跑下来没有明显等待。这一档给你一条可用的底线,不是最终形态。
升档条件写清楚再执行:调细一个维度后,延迟分布仍落在阈值 A 以内,异常样本没有增加,且主观体验没有出现新的等待,才保留这次调整;三个条件缺一个,就回退。
回退条件同样是三条:延迟超过 A、异常样本变多、或画面可玩性明显变差。回退时把该维度这一档记为当前环境下的上限,写进配置注释,下次不用重新试。
最后是需要确认的边界:HappyOyster 1.0 的参数名、日志字段和可调项以你本地版本为准,示例中的字段名都当占位符用。换机器、换地图规模、换联机人数之后,之前填的阈值和分级都要重测一遍再沿用。