下载 App
发布时间
发布时间
天一
还有另外一个问题:
谱面在 require 阶段做了大量“构建 + 校验”,再叠加 PvpCharts 的全量 eager require,导致客户端/服务端启动时都会被迫计算一遍。
关键链路:
main.lua 和 server_main.lua 都会 require("Data.PvpCharts")
Data/PvpCharts.lua 顶层直接 require 了所有谱面:被 require 时会立刻执行构建逻辑:
DDVSStandardChart.lua 最后调用 StandardChartBuilder.Build(...)
DDVSChart.lua 在文件加载时直接遍历所有 stage,生成 Chart.notes / pvpNotes / pvpNotesByStage
所以即使玩家还没选 DDVS,加载 PvpCharts 时 DDVS 的谱面计算已经执行了。
DDVS 两个文件的计算逻辑大概是这样:
按 stage 读取 CURATED_STAGE_TIMES
根据 CHORD_INDICES / TRIPLE_INDICES 把单点扩成单键、双押、三押
计算每段目标输入数:targetInputs = round((sourceEnd - playableStart) * targetNps)
统计实际输入数 actualInputs
用滑动 1 秒窗口算峰值输入:GetPeakInputs(notes)
做一堆 assert:
输入数必须等于目标
峰值不能超过难度限制
note 必须在 playable 区间内
lane 不能越界 / 重复
听杀段必须能达到 string break 需要的第 52 个输入
最后生成 PVP 用的 noteId、timeMs、lane、hitCount、baseScore 等运行时结构
我这边算了一下,DDVS 本身数据是对得上的:
Standard 总输入:365
Hard 总输入:478
每个 stage 的 targetInputs 和 actualInputs 都能对上
没看到明显的死循环或断言必炸点
但问题在于这些计算都是模块加载时执行,不是按需执行。并且 .meta 里 DDVSStandardChart.lua / DDVSChart.lua 都是:
group: default, #blocking
没有 c_or_s
这意味着它们很可能会同时进 client/server 包。再加上 client 和 server 都 require PvpCharts,就会出现:
服务端启动要算一遍所有谱面,客户端启动也要算一遍所有谱面。
真正风险是 PvpCharts.lua 顶层全量 require,导致所有谱面在启动时 eager build。
DDVSStandardChart.lua / DDVSChart.lua 这类文件不是纯配置,require 时会生成谱面、做 O(n²) 峰值校验、assert、print。
在 client/server 都需要的情况下可以保留 shared,但要明确这是运行时代码;如果某些谱面或预览数据只给客户端用,就应该用 c_or_s 明确隔离。
更推荐后续把 PvpCharts 改成 lazy load:只在 Resolve(trackId, difficultyId) 时 require 对应曲目和难度,避免启动时把所有谱面都构建一遍。
User763827286
星海幸存者,无广竖屏割草爽游,最近刚开双人联机活动,礼包码LB0001~LB0008