研究命题(00-plan):验证并打磨《围猎》联机纯音频体验——不是逻辑能跑通, 而是真人玩起来是什么体验、愿不愿意再来一局。 设施 web/harness/hunt-sim/(可复用,零依赖): - arena.mjs 编排器:起真实服务器(随机端口+临时数据目录隔离),10 个拟人客户端 经真实 WS 同时在线,错峰组队、真实时长对局、局间状态跨轮维护 - sim-client.mjs:game.js 行为移植(协议+手势路由+R1-R8 音频调度逐字节对齐), 产出「玩家耳朵听到什么」的感知时间线(语音全文/loop 方位音量档/喊话/震动) - brain.mjs:人设大脑——察觉延迟/前后判读(以真值为条件的正确率模型)/掩蔽放大/ 冷却乱滑/技能囤积/呼喊倾向/分心断网,全部随机判定用按实体 id 哈希的独立抽签 (mulberry32 流会被刷怪座位轮转结构带偏,实测造成系统性镜像反转,已证伪) - recorder.mjs:每人每局 events.jsonl 全量 + percept.md 感知转写 + 对局速览 研究档案 research/hunt-sim/: - players/:10 人配置(LLM 亲笔)+策略自述+逐局去留决策+人设终评+退游者重访 - rounds/:v1 三轮(R0 教学+R1/R2 真人快速)+ v2 复测两轮,共 48 局全记录 - analysis/01-04:数值曲线/音频信息设计/协作社交/上手留存四视角报告 - synthesis.md(S1-S9 裁定)、metrics.md/metrics-v2.md(两版对比总账)、report.md(总报告) v1 核心发现:10 人 3 轮 28 局 100% 胜率 26S/营地零损耗;击杀垄断(专家单人 30/39); 呼喊 3 次/28 局应答 0;N/S 前后判读仅 63/69% 可命中;四种退游死因 (失衡/社交真空/交互摩擦/观光无聊)→ 详见 report.md
20 KiB
02 · 音频信息流设计分析(Q2 方位判读 / Q3 信道拥挤)· Phase 2
视角:纯音频信息流——耳朵在每一秒能听到什么、能不能判读、被谁掩蔽。 数据:
metrics.md(28 局总账)+ 4 份抽样精读转写(P02/P08 · R1-quick,P07 · R2-quick,P10 · R0-teach)+ P01/P02/P09/P10 终评。 硬约束(全程自检):R6 红线——方位信息永远由声像承载,语音不得报方位;语音资产每句重新 TTS 有成本。 改动面缩写:G =web/hunt/game.js,S =web/server/hunt-room.js,V =docs/design/23-hunt-voice-ids.md(含tools/gen_voice_dual.py两表一致铁律),D =docs/design/23-hunt.md同步。
0. 总判断
信息流层面三个结构性断点,且互相放大:① 前后轴只有"音量 ×0.6"一条线索,且与距离档共用响度维度(混淆是数学上注定的);② 出击冷却 2.5s 对玩家是纯黑箱(666 次乱滑被拦,无一毫秒就绪信息);③ up/down 手势"有怪=出击、无怪=菜单/状态链"的语境折中,把方位判读弱点直接兑换成误触 UI 与语音轰炸。R1-R8 机制本身全部成立(无叠播、无超限),但 R2 的"占线丢弃"打在唯一正确的时机上(波始),bot 喊话在快速局近乎绝迹。掩蔽的代价不在判读准确率(10% vs 10%,无差异),而在漏检与迟到——当前指标没有这个口径,复测需补。
A1 · 前后轴(N/S 家族)判读 63-69%:单线索、且与距离轴共维度
现象(数据+转写引用)
- 混淆账(821 次登记,按 90° 弧可命中口径):N 63%(n=120)/ S 69%(n=85),而 E/W 100%、四斜向 96-99%。弱点严格落在 "pan=0、只能靠音量分前后" 的家族;N 同时是尝试量最大的桶(玩家默认往前滑)。
- 转写翻车样本(全部是前后翻转,不是左右混淆):
- P02 R1
00:45.7「以为左前实在正左」、01:11.4「上滑出击→以为正前的狼(其实在正后)」、01:18.9/01:44.7「以为正后(其实在正前)→下滑变菜单」; - P07 R2
01:44.2「以为正前其实在正后」、01:51.3「以为左前其实在正前——挥空」; - P10 R0
01:53.9「闷声以为左前,实在左后」、02:29.1「以为右后,其实在正前」。
- P02 R1
- 终评三方盖章:P01(资深,斜向混淆 <8% 的人设)「单音量线索在旁白轰炸下等于无线索」;P02「三局五验同判不同果,等于不可用」;P10「三局了这条规则从没进过我脑子」。
根因(三层,一层比一层深)
- 几何层:
pan = sin(az),N/S 同为 0——StereoPanner 前后同位是已知物理边界,设计已用 ×0.6 补偿;但 -4.4dB 是一个响度差。 - 维度混淆层(设计根源):距离三档 0.30/0.55/0.80 与前后系数 ×0.6 共用同一个响度维度,且量级相当(档间差 -5.2dB / -3.2dB vs 前后差 -4.4dB)。具体对撞:前方中档 0.55 vs 后方贴脸档 0.80×0.6=0.48——差 0.5dB,人耳不可分;后方中档 0.33 与前方远档 0.30 直接重叠。"多远"和"前还是后"两个信息轴被压进同一根响度刻度,这不是练不练的问题,是解码不出来。
- 实现与教学层:
- game.js
_ensureMobLoop里"闷"=vol × 0.6纯增益(G:961),没有任何低通滤波——设计词面"身后发闷"承诺的是音色,实现只给了响度; - 教学零覆盖:hunt-room.js
tickTeach的教学狼全在前半平面(stage1dir:'N'、stage2N+NE,S:591/606-607),tut_rule台词不含闷约定(voice-ids 头注写"由音效演示承担"——演示狼根本不从身后来)。P10 终评 P0-1 原话:「闷=身后零教学」。
- game.js
修复提案(全部不越 R6 红线:方位仍由声像/音色承载,无语音报方位)
| # | 修法 | 机制/参数 | 改动面 | 新台词? |
|---|---|---|---|---|
| F1 | 后半平面低通第二线索(音色轴) | loop 链路 src→gain→BiquadFilter(lowpass, f≈900Hz, Q≈0.7)→panner→sfxBus,后半平面启用、前半平面直通;与 ×0.6 音量并行。音色与响度正交,距离档不再污染前后判读。loop 走游戏层自建节点(abyss 先例),不动引擎面 |
G(_ensureMobLoop) |
否 |
| F2 | 前后系数加深 | ×0.6→×0.5(-6dB),配合 F1 后响度只做辅助确认 | G(一行常量)+D §8.3 同步 | 否 |
| F3 | 教学补"身后"课 | T1 杀掉 N 狼后补放一只 dir:'S', eta:12 教学狼(同样零惩罚、可挥空重教 ≤2 次);新台词点破:tut_back「这一声发闷——它在身后。声音发闷,就在背后。」;同时换写既有 tut_rule:「野兽会从八个方向围上来。声音在哪边,就往哪边滑。听着发闷的,在身后。」(重生成,不加 id) |
S(tickTeach)+V(+1 id) |
是:新增 tut_back 1 id ×2 性别;tut_rule + key 变体各重生成 ×2。预算说明:旁白 60 句已打满,+1 需设计裁决(扩到 61,或砍 1 句低价值句腾位;候选:st_wave_c「最后一波了」与 wave_band5 语义重复度最高,但状态链在用——建议直接扩容并更新 D §10.3/自检 #5 口径) |
| F4 | 挥空增亮反馈(错向的真话由声像自己说) | ev miss 后 0.3s 内,把当前内圈 eta 最小怪的 loop 短暂增亮 0.6s(vol×1.3;若在身后,这 0.6s 暂时解除低通)——玩家当场听到"真实方位",形成前后轴的即时纠错学习回路 |
G(_onMiss → _highlightNearest) |
否 |
| F5 | (P2 备选)呼啸 howl 同样加低通 | howl 走引擎 opts.pan one-shot,插滤波需引擎面例外——与 §9"引擎改动唯一一处"冲突,暂缓;外圈损失由中圈 loop(已带 F1)接管 |
(引擎例外,暂缓) | 否 |
预期指标变化
- N/S 可命中率 63%/69% → ≥85%(R4 同口径复测);斜向 96-99% 与 E/W 100% 不回归(F1 不动 pan)。
- 前后翻转型挥空(转写归因"以为前/其实在后"类)样本占比下降 ≥60%;P02 类"同判不同果"主观报告消失(F1 使线索可解码,F3/F4 使其可学习)。
- P10 类新手「闷声判反两次」→ 教学局内至少一次正确应对身后世狼。
A2 · 冷却黑箱:666 次乱滑被拦,就绪状态零外显
现象
- 全场 666 次冷却乱滑被拦;P07 R2 一局 138 次(
01:48.3-01:49.7十一连滑、02:21.1-02:22.7又十余次,每 100-300ms 一记 error 震,间夹 threat 重听);P09 三局局局「回神头两秒全在吃震」,P10「三局从没数清过一次冷却」「一度以为是我滑法不对」。 - 实现现状(G):
_attackDir冷却内vibrate('error'); return;——2.5s 冷却没有任何音/震/节拍外显;旋风斩 8s 有skill_ready语音,但queue:true排队在拥挤信道里迟到:P07 R202:25.3战斗最烈时排不上,02:32.7局已进入结算才播出来(_enterEnd未清_skillReadyTimer,跨局泄漏,bug 级)。 - 附带偏差(需核查):P02 R1
00:37.2/00:38.1/00:39.0三次被拦右滑,转写播了gd_invalid「这个操作现在用不上」——设计口径是"冷却仅 error 震、gd_invalid onceKey 同局 1 次"。sim 感知模型与 game.js 两处不符(或真实客户端存在异常路径),实施前先对 harness 复刻核对。
根因
就绪状态只存在于客户端 _atkReadyAt 时间戳,没有任何模态把它交给耳朵/手掌;error 震语义是"不行"而不是"还差多久";冷却被拦与无效手势用同一种震(P10 三局分不清是冷却还是手势错);skill_ready 绑在语音队列上,信道越挤越迟到。
修复提案
| # | 修法 | 机制/参数 | 改动面 | 新台词? |
|---|---|---|---|---|
| F6 | 出击就绪双信号 | 冷却到期播 0.2s 合成短音 atk_ready(SYN 高频双 blip,中央,vol 0.5,R5 合规 <1s)+轻触觉(vibrate('confirm'))。节流:仅当本冷却窗内发生过被拦尝试才播(没人急着出手时不出声,避免每 2.5s 空响成噪声) |
G(_attackDir 内 arm setTimeout,复用 _armSkillReady 模式)+1 条程序合成 sfx |
否(SYN 无 TTS) |
| F7 | 被拦反馈分级 | 同一冷却窗内首次被拦:专用触觉模式(0.4s 双脉冲,与"无效手势"单短震区分);第 2 次起合并静默至窗尾(消灭 P07 式连震风暴)。冷却与无效手势两种 error 从此可分辨 | G(_attackDir + _invalid) |
否 |
| F8 | skill_ready 去语音化+修跨局泄漏 | 改合成 earcon(上行双音 0.3s)+success 轻震;_enterEnd/_teardownRound/stop 一律清 _skillReadyTimer;skill_ready 语音 id 保留给 TEACH 讲解用 |
G(_armSkillReady、_enterEnd)+1 条 SYN sfx |
否 |
| F9 | (P2 可选)冷却进度 tick | 被拦时按剩余时间给 1-3 声短 tick(P02 要的"还差半秒");有 F6 后收益边际化 | G | 否 |
预期指标变化
- 冷却乱滑被拦 666 → ≤200(就绪可听后 spam 自熄:P07 类玩家的连滑在第一声 ready 后失去动机)。
- P09「回神头两秒吃震」消除;P10「扣的那 1 分」收回;
skill_ready跨局/迟到播报归零(语音打断 37 次中 skill_ready 相关子项清空)。
A3 · down/up 双语义陷阱:误触菜单与状态链误播
现象
- 下滑=菜单误触,6/10 玩家中招:P01 R1 连环 14 次(终评:「下滑退出和下滑打正后是同一根手指,三次下滑全弹回菜单」);P07 R2
01:15.6-01:17.6菜单乒乓 6 轮(每轮sys_menu→回到猎场→settings_hint三句链互相打断,"回到猎场"四度播不完);P02 R1 五次(01:18.9/01:44.7/02:20.9-02:21.3连环);P08 R1 三次;P09 三局同坑(进菜单后01:09.3盲单击又误触"重新听帮助")。 - 上滑=状态链误播:错向挥出的上/下滑恰好制造"弧内无怪"→ 变成播报。P02 R1
01:11.4「以为正前其实在正后→上滑变成 4 句状态链」;P07 R201:44.2同型。状态链 4 句 ≈5-6s 占满语音通道(见 A4)。 - 菜单打开战斗照走(E3 豁免本意),P01 终评 P0-1 定性:「操作本身就是在跟系统打架」。
根因
23-hunt §2.1 表格自身双重定义(四向滑=出击 vs 上滑=状态链/下滑=菜单);game.js 文件头"语境折中"用 _arcHasTarget()(客户端本地、eta≤4、事件流瞬时空窗都影响判定)做分流——把"打不打得到"这个毫秒级动态事实当作"出招还是开 UI"的开关。且误触率与 A1 前后弱点正相关:错向 → 无怪 → 菜单。退出菜单仍是下滑,同一根手指解自己上的锁。
修复提案
| # | 修法 | 机制/参数 | 改动面 | 新台词? |
|---|---|---|---|---|
| F10 | WAVE 态下滑恒=出击 | 无目标也走完整出击:atk_whoosh+服务器 miss → atk_swish 真话+error 震(与左/右滑同待遇)。菜单入口改为:①波间休整(wave_clear 后 8s 窗)内下滑=菜单;②战斗中长按=菜单(WAVE 态旁白极少,快进让渡成本最低——需宪法裁决登记 E3 修订);若裁决不动长按,则战斗中无菜单、退出只在波间 |
G(_onWaveGesture)+D §2.1/§2.4/§2.5 豁免表同步 |
否 |
| F11 | 上滑状态链两条护栏 | ①链播中再上滑=立即停止(现在会再排 4 句,P02 R0 23 秒里"营地固若金汤"五遍);②危急截断:任一怪进入贴脸档(eta<2.5s)时,正在播的状态/菜单/帮助/watchdog 链立即截断(_chainSeq+++stopVoice;警报/教学/结算链豁免)——即 P02 点名的"危急时刻静默通道",实现"loop 优先"而不动引擎 ducking |
G(_statusChain、_refreshLoops 内挂钩) |
否 |
| F12 | 状态链瘦身 | 4 句→按变化播:耐久档+击杀档恒播;波次档仅波次变更后首次播;猎人数仅 roster 变更后播(P08 是状态链重度用户且终评正向——保留主干只砍复读) | G(_statusIds) |
否 |
预期指标变化
- 战斗中 menu-open 误触:P01 的 14 次/局 → 0(结构性消除)。
- 语音打断 37 → ≤15(大头是菜单乒乓互切,见 A4 清单)。
- "状态链压贴脸脚步"型掩蔽案例(P02 R2 01:21.0-01:26.8)归零;P01 P0-1/P0-2 直接收口。
A4 · 语音通道 × 战斗信息冲突账
掩蔽源清单(按占用时长与伤害排序;样本来自 4 份精读转写)
| 源 | 单次占用 | 样本频次 | 价值裁定 |
|---|---|---|---|
误触菜单链(sys_menu+sys_menu_resume+settings_hint) |
3 句 ≈5s | P02 R1 ×5、P07 R2 菜单乒乓期近连续、P08 R1 ×3 | 负价值;F10 后归零 |
help_main 战斗中整播 |
≈8s | P08 R1 01:33.4/02:02.3、P07 R2 01:40.9、P01 R1 ×2 |
负价值(P01:「对老手重播基础教学=战斗中没收我的耳朵」);F10 后结构性消失(菜单不在战斗态) |
| 状态链 4 句 | ≈5-6s | P08 R1 主动使用 ×6;P02 R0 23s 五遍复读 | 中价值(P08/P06 靠它感知战局)——瘦身保留(F11/F12),不删功能 |
watchdog 两级(idle 提示音+gd_idle) |
≈2s×2 | 全场 93 次 ≈3.3 次/局;P10 R2 七次全误伤(在等怪不是挂机) | 救命索但触发条件错(P09 走神 9 次全被拽回)。修:inner-ring 有怪、或 5s 内有击杀/被拦/呼喊记录时不触发;第 1 级降为纯震+短音,第 2 级才上语音(G _rearmWatchdog 条件) |
波次/威胁/警报(wave_band*/threat_*/breach*) |
各 1 句 | 合法占用 | 警报可达性 PASS:28 局 6 次 breach 全部按时到达并正确顶掉状态类(R1 实测有效);threat_* 重听是 P07 的双击主出口,属宪法语义,保留 |
skill_ready |
1 句 | P07 R2 高频 | F8 去语音化后退出竞争 |
掩蔽 × 误判的诚实读数
metrics:掩蔽下误判率 10%(n=297)vs 干净时 10%(n=524)——判读准确率不受掩蔽影响(拟人模型"听到后"的判读与掩蔽无关)。但掩蔽的真实代价是漏检/迟到:P01「menu 播报正好盖掉右后闷脚步→四连打空」、P02「状态链四句压着贴脸脚步」。当前混淆账不测这个。复测新增指标:「掩蔽窗漏检率」=语音在播期间进入内圈的怪,玩家首次针对性出手延迟 >1.5s 的比例(基线值 R4 复测时先量再比)。
bot 喊话饿死(结构性对撞)
- R2 客户端规则"旁白在播→延迟 ≤2s→丢弃",撞上服务端触发时机:
greet排在开局(GREET_FIRST_MS起,S:352-353)、wave排在波始(S:371)——这两个时刻旁白必播(room_start+wave_band1/wave_bandN),氛围句 2s TTL 必死。 - 实测:P10 R0 教学局 12 条 botline 中 7 条被挤掉(
00:04.6greet、01:07.3/02:11.5/02:43.1恰为波始),5 条可闻(help_call/help_ack/cover/kill×2——priority 句 4s TTL 兑现了"呼救不可被顶");P02/P07/P08 三份快速局转写可闻 bot 喊话 0 条。 - 注意另一根因:P01 R1 是 4 真人房(0 bot),bot 喊话结构性为零——"真人房社交声道缺失"要靠呼喊链路补(全场呼喊仅 3 次/28 局,且 P02 R1
02:12.6呼喊的本地反馈在转写里呈现为旁白"重新听帮助。",同房 P01 也没报告听到空间化喊话——呼喊播放链路需专项核查)。
修法 F13(S+G,无新台词):服务端 wave/greet botline 延迟 3.5s 投递(等 wave_band 播完;BOTLINE 预算 10s≤2 不变);客户端非优先句 TTL 2s→4s。预期:快速局人均可闻喊话 0→3-5 条;教学局挤掉 7→≤2。
A5 · R1-R8 拥挤规则在真实并发下的表现
| 规则 | 机制是否成立 | 真实并发下的表现与裁定 |
|---|---|---|
| R1 旁白单句队列 | ✅ | 全程无叠播;警报顶状态类实测有效(breach 到达 6/6)。代价=队列拥堵与打断(37 次,主因菜单乒乓,F10 后大减);发现的 bug:skill_ready 排队跨入结算链(P07 R2 02:32.7),F8 修复 |
| R2 喊话 sfx ≤1+延迟丢弃 | ✅(但丢弃打错时机) | 上限无违例;丢弃全落在 greet/wave 两类"旁白必播时刻"——修触发时机(F13),不放宽 ≤1 上限。help_call/help_ack 优先级兑现(教学局 5 条可闻里 3 条是 priority) |
| R3 loop ≤3 路 | ✅ 且无害 | 无"第 4 近怪因静默突入"的可归因案例(快速局 6 局全零 breach);被裁剪怪的方位由击杀倒地音(带 pan)部分补偿。维持原样 |
| R4 one-shot ≤2+呼啸可弃 | ✅ | 波 4-5 生成潮确有呼啸被弃(外圈方向预告缺失),但中圈起 loop 接管,本数据集无可归因损失。可选微调 HOWL_QUEUE_MAX 2→3 / TTL 1.5→1.2s——收益小,列 P2 |
| R5 非语音 <1s | ✅ | 无违例 |
| R6 方位由声像承载 | ✅ | 全程无语音报方位。这是立身之本:本报告所有修法(低通/增亮/earcon)均让声像自己说话,明确拒绝"语音报前后"类越线捷径 |
| R7 电平分层 | ⚠️ 半成立 | BGM duck 语音方向正确;但"语音 vs loop"无互让——用 F11 危急截断在游戏层实现"贴脸 loop 优先",不动引擎 |
| R8 ≤7 声流 | ✅ | 转写无超限/叠爆证据 |
修复优先级表
| 级 | 编号 | 修法 | 改动面 | 新台词(TTS 成本) | 预期指标 |
|---|---|---|---|---|---|
| P0 | F1 | 后半平面 loop 低通(音色第二线索) | G | 否 | N/S 63/69% → ≥80%(配合 F3 冲 ≥85%) |
| P0 | F6 | 出击就绪 earcon+触觉(有被拦才播) | G+1 SYN sfx | 否(程序合成) | 乱滑被拦 666 → ≤200 |
| P0 | F10 | WAVE 下滑恒出击;菜单改波间窗/长按 | G+D(E3 修订) | 否 | 战斗中误触菜单 →0;语音打断 37 → ≤15 |
| P0 | F3 | 教学补身后期:S 向教学狼+tut_back+tut_rule 换写 |
S+V | 是:+1 id×2 性别;tut_rule(含 key 变体) 重生成 ×4;60 句预算需裁决扩容 |
新手前后翻车率减半;「闷」从零教学变一课学会 |
| P1 | F11 | 危急截断+链中再上滑即停 | G | 否 | 状态链压贴脸脚步案例归零 |
| P1 | F7 | 被拦反馈分级(冷却≠无效手势,连震合并) | G | 否 | P10 类"自我怀疑"消除 |
| P1 | F13 | botline 波始延迟 3.5s+客户端 TTL 2→4s;呼喊链路专项核查 | S+G | 否 | 快速局可闻喊话 0→3-5 条/人 |
| P1 | F8 | skill_ready 去语音化+局末清 timer | G+1 SYN sfx | 否 | 跨局泄漏/迟到归零 |
| P1 | F12 | 状态链按变化播(4 句→2-4 句) | G | 否 | "固若金汤"复读投诉归零,状态感知功能保留 |
| P2 | F4 | 挥空增亮(0.6s 突出真方位 loop) | G | 否 | 前后错向即时纠错学习回路 |
| P2 | F2 | 前后系数 0.6→0.5 | G+D §8.3 | 否 | F1 的响度辅助确认 |
| P2 | F5/F9 及 watchdog 降级、HOWL 队列微调 | 见 A4/A5 | G/S | 否 | 边际改善 |
汇总账:12 项修法中仅 F3 需要新台词(1 个新 id + 1 个既有 id 换写重生成,合计 6 条 TTS:tut_back×2 性别、tut_rule×2 性别+key 变体×2);其余全部是 game.js / hunt-room.js 逻辑与程序合成 sfx,零 TTS 成本。全部修法通过 R6 红线自检(无一句语音报方位)。
复测口径提醒(给 synthesis):①混淆账同口径重跑(N/S 家族单列);②新增"掩蔽窗漏检率";③新增"战斗中 menu-open 次数""被拦后至就绪出手的中位延迟""bot 喊话可闻条数/人/局";④先核对 sim 感知模型两处偏差(冷却被拦播 gd_invalid、呼喊本地反馈异常),确保 R4 对比不被 harness 噪声污染。