Top Speed 赛道创建指南

目录

1. 简介 2. 作为作者,该如何想象赛道形状 3. 文件夹布局、文件发现与加载规则 4. TSM 文件格式规则 5. 各部分以及它们如何关联 6. 详细键参考 6.1 Meta 部分 6.2 天气配置部分 6.3 Room 部分 6.4 Segment 部分 6.5 声源部分 6.6 值解析与标记规则 7. 房间混响模型与完整预设目录 7.1 混响参数含义 7.2 完整内置房间预设 8. 完整示例 TSM 赛道文件 9. 验证与故障排查 10. 实用创作流程

1. 简介

本指南记录了 Top Speed 当前使用的自定义赛道格式,内容基于当前解析器与运行时代码路径整理而成。它是一份创作参考文档,而不是宣传概览,因此核心目标是实用且准确。

一个自定义赛道文件会同时控制四个方面:道路形状与路面流向、启用的天气模型及其过渡行为、车辆穿过各赛道段时所应用的声学房间配置,以及放置在赛道上的可选自定义声源。这些系统都通过 id 相互关联,并且会在赛道被接受前完成验证。

这意味着,制作赛道不仅仅是写出合法的键。你还需要理解:哪些键会真正被运行时消费,哪些键只是元数据,极端值经过钳制后会如何变化,以及哪些引用必须事先存在。

2. 作为作者,该如何想象赛道形状

最准确的心智模型,是把整条赛道看作一条会循环重放的赛道段时间线。赛道段顺序,就是赛道顺序;赛道段长度,是以米为单位的真实物理距离;弯道类型则决定玩家在通过该赛道段时,车道中心会以多快的速度向左或向右偏移。

straight 会让横向中心偏移保持为零。左右弯道则会以不同强度产生连续偏移。由于偏移是在整段长度上累计计算的,因此在弯道类型相同的情况下,长赛道段会比短赛道段产生更大的累计中心位移。

当前运行时使用的弯道强度系数如下:

赛道段宽度与弯道形状是分开的。如果 width > 0,该赛道段就会使用它自己的宽度;如果 width <= 0,运行时会回退到默认车道宽度。这会显著影响赛道手感,因为完全相同的弯道序列,在不同宽度配置下,可能会显得宽容,也可能会显得苛刻。

一个实用的工作流是:先只编写赛道段顺序、长度和宽度,先开起来、调整节奏;等几何形状手感正确之后,再加入天气、房间和自定义声音。

3. 文件夹布局、文件发现与加载规则

自定义加载既可以接受文件夹路径,也可以接受文件路径。如果传入的是文件夹,加载器会扫描该文件夹中的 *.tsm 文件,并按照不区分大小写的排序顺序选取文件名排在最前的那个;如果传入的是文件路径,它必须是一个位于现有文件夹中的 .tsm 文件。

推荐布局如下:

Tracks/
  MyTrack/
    track.tsm
    Audio/
      ambience_loop.ogg
      birds_1.ogg

声源部分中的声音路径,是相对于 tsm 文件所在文件夹来解析的。它们不会相对于游戏根目录解析,也不会相对于 Sounds 资源根目录解析。这样可以保证每个自定义赛道都是自包含的。

自定义赛道的显示名称解析顺序如下:

  1. 如果 meta.name 已定义且非空,则优先使用它。
  2. 使用父文件夹名称。
  3. 使用不带扩展名的文件名。

4. TSM 文件格式规则

TSM 是基于行的格式,并且只支持两种语句形式:部分头和键值赋值。

部分头格式:

[kind]
[kind:id]

键值格式:

key = value

行内注释以 # 开始,并会在解析前被剥离。空行会被忽略。

支持的部分类型包括 metasegmentweatherroomsound。其中 segmentweatherroomsound 都要求带 id(即 [kind:id]);meta 不使用 id(即 [meta])。

未知的部分类型会导致验证失败。严格部分中的未知键同样会导致验证失败,唯一例外是那些以 metametadata 开头的扩展式键。

部分顺序是灵活的。解析器会自上而下读取,并在遇到新的部分头时,将前一个部分对象封存完成。同一部分中重复同一个键是允许的;在该部分对象内部,后写的值会覆盖先前的值。

键名和部分类型在解析时会被规范化为小写,并把空格与连字符转换成下划线。id 会先去掉首尾空白,并以不区分大小写的方式匹配。id 唯一性是按部分家族(segmentweatherroomsound)分别强制执行的,因此同一家族内出现重复 id 会被视为验证错误。

5. 各部分以及它们如何关联

赛道至少需要一个 segment 部分。此外,meta.weather 也是必填项,并且它必须指向一个已存在的天气配置 id。如果这两者任何一个缺失,赛道都会被拒绝。

赛道段是整条赛道的骨架,它们可以引用:

声源还可以通过 start_areaend_area 来引用赛道段 id,因此赛道段 id 同时会被几何系统和音频触发逻辑使用。

房间行为有两层覆盖关系:

天气行为也有两层:

6. 详细键参考

6.1 Meta 部分

本部分的头写法是 [meta]

name

这是自定义赛道在菜单和播报中使用的显示名称。
允许的值: - 任意非空文本值。

version

这是可选的作者元数据,用于你自己的版本修订。
它会和赛道数据一起存储,但本身不会直接改变运行时的驾驶或音频行为。
允许的值: - 任意非空文本值。

weather

这是赛道必填的默认天气配置 id。
允许的值: - 任意已存在的天气部分 id。 - 例如:如果文件中包含 [weather:clear],那么 weather = clear 就是合法的。 - 如果该 id 不存在,加载会失败。

ambience

这个键用于选择旧式环境循环音家族。
允许的值: - none
禁用旧式环境循环音播放。 - desert
使用沙漠环境循环音行为。 - airport
使用机场环境循环音行为。

别名值: - 0: none - noambience: none - 1: desert - 2: airport

6.2 天气配置部分

部分头写法为 [weather:<id>],例如 [weather:clear]

kind

这个键用于选择该配置的基础预设。
当设置了这个键时,运行时会先加载该预设值,然后再应用同一个天气部分中显式写出的数值键。
允许的值: - sunny
晴天基线,风力中性、能见度较长。 - rain
雨天配置基线,更强调湿润环境音。 - wind
大风配置基线,具有更强的横风。 - storm
暴风雨配置基线,天气强度最高。

别名值: - 0: sunny - 1: rain - rainy: rain - 2: wind - windy: wind - 3: storm - stormy: storm

longitudinal_wind_mps

这是沿驾驶轴方向的风分量,单位是米/秒。
正值相当于迎风,会提高相对风速;负值相当于顺风。
允许的值: - 任意有限数值。

lateral_wind_mps

这是横风分量,单位是米/秒。
它会把侧向空气速度计入空气阻力大小。
允许的值: - 任意有限数值。

air_density

它控制空气动力计算中使用的空气密度,单位为 kg/m³。
允许的值: - 任意大于 0 的数值。

运行时说明:如果构造阶段仍然收到无效的非正值,就会回退为 1.225

drafting_factor

这是阻力模型中直接作用于空气阻力的乘数。
1.0 表示中性;大于 1.0 会增加阻力;小于 1.0 会减少阻力。
允许的值: - 任意大于 0 的数值。

运行时说明:构造阶段的钳制会强制它不低于 0.1

temperature_c

它以摄氏度存储天气温度,用于配置状态。
当前驾驶阻力逻辑并不直接依赖这个键,但它仍然是天气配置数据的一部分。
允许的值: - 任意有限数值。

humidity

它以归一化比值形式存储相对湿度。
允许的值: - 任意位于 01 之间的数值。

运行时说明:在天气配置构建时,值会被钳制到 0..1

pressure_kpa

它以 kPa 为单位存储大气压。
允许的值: - 任意大于 0 的数值。

运行时说明:如果构造阶段收到无效的非正值,会回退为 101.325

visibility_m

它以米为单位存储天气配置的能见度距离。
允许的值: - 任意大于 0 的数值。

运行时说明:如果构造阶段收到无效的非正值,会回退为 20000

rain_gain

这个值设定该配置中雨声循环的天气强度增益。
允许的值: - 任意大于或等于 0 的数值。

运行时说明:配置内部会在钳制后存储 0..4;当前播放路径在真正应用到声源音量前,还会再做一次最终 0..1 钳制。

wind_gain

这个值设定该配置中风声循环的天气强度增益。
允许的值: - 任意大于或等于 0 的数值。

运行时说明:配置内部会在钳制后存储 0..4;当前播放路径在真正应用到声源音量前,还会再做一次最终 0..1 钳制。

storm_gain

这个值设定该配置中暴风声循环的天气强度增益。
允许的值: - 任意大于或等于 0 的数值。

运行时说明:配置内部会在钳制后存储 0..4;当前播放路径在真正应用到声源音量前,还会再做一次最终 0..1 钳制。

天气切换行为:
当某个赛道段设置了 weather = some_id 时,运行时会逐步混合过渡到该配置。
混合速度由赛道段键 weather_transition_seconds 控制。

6.3 Room 部分

部分头写法为 [room:<id>],例如 [room:tunnel_a]

name

这是该房间配置的可选可读标签。
允许的值: - 任意非空文本值。

room_preset

这个键用于选择初始化房间声学时所使用的内置预设基线。
同一部分中的任何数值型房间键,都会覆盖这条基线。
允许的值: - 第 7.2 节列出的任意预设 id。

reverb_time

它控制房间混响尾音的总衰减时长,单位为秒。
允许的值: - 任意数值。 - 运行时会将其钳制为非负。

reverb_gain

它控制房间混响回传的整体电平。
允许的值: - 任意数值。 - 运行时会钳制到 0..1

hf_decay_ratio

它控制高频在混响尾音中相对低频/中频的衰减速度。
值越低,高频越快变暗;值越高,高频亮度保留得越久。
允许的值: - 任意数值。 - 运行时会钳制到 0..1

late_reverb_gain

它控制后期尾音成分(后期反射)的增益。
允许的值: - 任意数值。 - 运行时会钳制到 0..1

diffusion

它控制反射的密度和平滑度。
值越低,反射听起来越分散、颗粒感越重;值越高,反射会更顺滑、更稠密。
允许的值: - 任意数值。 - 运行时会钳制到 0..1

air_absorption

它控制声音在空气中传播时损失多少高频内容。
值越低,远处声源仍会保持较亮;值越高,远处声音会更快变闷。
允许的值: - 任意数值。 - 运行时会钳制到 0..1

occlusion_scale

它控制障碍物对直达声路径的削弱程度。
值越低,障碍物的遮挡感越弱;值越高,障碍物的遮挡感越强。
允许的值: - 任意数值。 - 运行时会钳制到 0..1

transmission_scale

它控制声音穿过墙体或重型结构等边界的泄漏程度。
值越低,隔墙声音越弱、阻隔感越强;值越高,穿透过去的声音越多。
允许的值: - 任意数值。 - 运行时会钳制到 0..1

occlusion_override

这是一个可选的直接遮挡值。
一旦设置,它会覆盖房间/配置路径中派生出来的遮挡量。
允许的值: - 任意数值。 - 设置后,运行时会钳制到 0..1

transmission_override

它设置一个传输覆盖值,并把它同时应用到低、中、高三个频段。
当你想要一个全局传输覆盖,而不是逐频段微调时,就可以用它。
允许的值: - 任意数值。 - 设置后,运行时会钳制到 0..1

transmission_override_low

它设置低频段传输覆盖值。
允许的值: - 任意数值。 - 设置后,运行时会钳制到 0..1

transmission_override_mid

它设置中频段传输覆盖值。
允许的值: - 任意数值。 - 设置后,运行时会钳制到 0..1

transmission_override_high

它设置高频段传输覆盖值。
允许的值: - 任意数值。 - 设置后,运行时会钳制到 0..1

air_absorption_override

它设置一个空气吸收覆盖值,并同时作用于低、中、高三个频段。
允许的值: - 任意数值。 - 设置后,运行时会钳制到 0..1

air_absorption_override_low

它设置低频段空气吸收覆盖值。
允许的值: - 任意数值。 - 设置后,运行时会钳制到 0..1

air_absorption_override_mid

它设置中频段空气吸收覆盖值。
允许的值: - 任意数值。 - 设置后,运行时会钳制到 0..1

air_absorption_override_high

它设置高频段空气吸收覆盖值。
允许的值: - 任意数值。 - 设置后,运行时会钳制到 0..1

赛道段引用行为:
一个赛道段可以引用 room 部分 id,也可以直接引用预设 id。
如果赛道段级房间覆盖存在,那么它们会在选中的房间基线之后再应用。

6.4 Segment 部分

部分头写法为 [segment:<id>],例如 [segment:s12]

type

这个键用于设置该赛道段的弯道类别。
所选类别会影响道路中心在这段距离推进过程中如何偏移。
允许的值: - straight
无横向偏移。 - easy_left
轻微向左偏移。 - left
中等向左偏移。 - hard_left
强烈向左偏移。 - hairpin_left
非常强的向左偏移。 - easy_right
轻微向右偏移。 - right
中等向右偏移。 - hard_right
强烈向右偏移。 - hairpin_right
非常强的向右偏移。

别名值: - 0: straight - 1: easy_left - 2: left - 3: hard_left - 4: hairpin_left - 5: easy_right - 6: right - 7: hard_right - 8: hairpin_right

surface

这个键用于设置赛道段的路面类别。
允许的值: - asphalt
标准铺装路面行为。 - gravel
松散路面行为。 - water
湿滑/低抓地行为。 - sand
柔软路面行为。 - snow
类雪地低抓地行为。

别名值: - 0: asphalt - 1: gravel - 2: water - 3: sand - 4: snow

noise

这个键用于设置旧式赛道段噪音行为。
允许的值: - none
无旧式赛道段噪音。 - crowd
人群环境音行为。 - ocean
海洋环境音行为。 - runway
跑道/飞机行为。 - clock
时钟环境音行为。 - jet
喷气机事件行为。 - thunder
雷声事件行为。 - pile
堆场环境音行为。 - construction
施工环境音行为。 - river
河流环境音行为。 - helicopter
直升机事件行为。 - owl
猫头鹰事件行为。

别名值: - 0: none - nonoise: none - off: none - 1: crowd - 2: ocean - 3: runway - 4: clock - 5: jet - 6: thunder - 7: pile - 8: construction - 9: river - 10: helicopter - 11: owl

length

这个键用于设置赛道段长度,单位为米。
解析器会强制执行最小赛道段长度阈值。
允许的值: - 任意数值。
低于当前解析器最小值的内容会给出警告,并被钳制。
当前默认最小值是 50 米。

width

这个键用于设置该赛道段的宽度覆盖值,单位为米。
允许的值: - 任意数值。 - 运行时会将其钳制为 >= 0。 - 非正值会回退到默认车道宽度。

height

它存储赛道段高度值。
允许的值: - 任意数值。 - 会被解析并存储,但当前活动道路几何行为并不会使用它。

weather

这个键为该赛道段指定天气配置 id。
允许的值: - 仅限已存在的天气配置 id。

weather_transition_seconds

这个键设置进入该赛道段天气配置时的混合持续时间。
允许的值: - 有限且 >= 0 的数值。

room

这个键为该赛道段指定房间/声学来源。
允许的值: - 已存在的 room 部分 id。 - 内置房间预设 id。

别名键: - room_profile: room - room_preset: room

room_profile

这是 room 的别名键。
允许的值: - 与 room 相同。

room_preset

这是 room 的别名键。
允许的值: - 与 room 相同。

sound_sources

它将声源 id 直接分配给该赛道段。
允许的值: - 已存在声源 id 的逗号分隔列表。

别名键: - sound_source_ids: sound_sources

sound_source_ids

这是 sound_sources 的别名键。
允许的值: - 与 sound_sources 相同。

额外的赛道段说明:
房间数值键和房间覆盖键也可以直接出现在赛道段部分中。
当它们存在时,只会覆盖这个赛道段的房间声学效果。

简单成形策略:

  1. type + length 构建形状。
  2. 设定稳定的 width 宽度带。
  3. 加入 surface
  4. 加入天气/房间过渡。
  5. 最后再加声音。

6.5 声源部分

部分头支持两种形式:

例如:[sound_random:wind_gusts] 会隐式设置 type = random

type

这个键用于设置声源行为类型。
允许的值: - ambient
环境型声源行为。 - static
固定声源行为。 - moving
路径/运动驱动型声源行为。 - random
变体选择型声源行为。

别名值: - 0: ambient - 1: static - 2: moving - 3: random

path

主声源文件路径。
允许的值: - 仅限相对于赛道的路径。

别名键: - file: path

file

这是 path 的别名键。
允许的值: - 与 path 相同。

variant_paths

用于选择的额外文件变体。
允许的值: - 逗号分隔的赛道相对文件路径列表。 - 空列表无效。

variant_source_ids

通过引用其他声源 id 来添加额外变体。
允许的值: - 已存在声源 id 的逗号分隔列表。 - 空列表无效。

random_mode

变体刷新模式。
允许的值: - onstart
在创建/启动时选择一次变体,之后保持不变。 - perarea
当区域/赛道段上下文变化时刷新变体。

别名值: - 0: onstart - 1: perarea

loop

循环播放标志。
允许的值: - true
启用。 - false
禁用。

别名值: - 1: true - 0: false - yes: true - no: false - on: true - off: false

spatial

启用空间化声源行为。
允许的值: - true
启用。 - false
禁用。

别名值: - 1: true - 0: false - yes: true - no: false - on: true - off: false

allow_hrtf

允许空间化路径中使用 HRTF。
允许的值: - true
启用。 - false
禁用。

别名值: - 1: true - 0: false - yes: true - no: false - on: true - off: false

global

让声源全局保持激活,而不受区域/赛道段门控限制。
允许的值: - true
启用。 - false
禁用。

别名值: - 1: true - 0: false - yes: true - no: false - on: true - off: false

volume

基础声源增益。
允许的值: - 任意数值。 - 运行时会钳制到 0..1

fade_in

淡入时间,单位秒。
允许的值: - 任意数值。 - 运行时会钳制为非负。

fade_out

淡出时间,单位秒。
允许的值: - 任意数值。 - 运行时会钳制为非负。

crossfade_seconds

变体切换时的交叉淡化时间。
允许的值: - 任意数值。 - 运行时会钳制为非负。

pitch

播放音高系数。
允许的值: - 任意数值。 - 运行时会把 <= 0 的值替换成 1

pan

立体声声像值。
允许的值: - 任意数值。 - 运行时会钳制到 -1..1

min_distance

空间化最小距离设置。
允许的值: - 任意数值。

max_distance

空间化最大距离设置。
允许的值: - 任意数值。

rolloff

空间化距离衰减设置。
允许的值: - 任意数值。

start_area

激活起始用的赛道段 id 触发器。
允许的值: - 仅限已存在的赛道段 id。

end_area

激活结束用的赛道段 id 触发器。
允许的值: - 仅限已存在的赛道段 id。

start_position

激活起始位置。
允许的值: - 向量文本 x,y,z

end_position

激活结束位置。
允许的值: - 向量文本 x,y,z

position

静态或锚点位置。
允许的值: - 向量文本 x,y,z

start_radius

起始位置触发半径。
允许的值: - 任意数值。

运行时说明:若缺失或为非正值,在触发判定时会回退为 1 米。

end_radius

结束位置触发半径。
允许的值: - 任意数值。

运行时说明:若缺失或为非正值,在触发判定时会回退为 1 米。

speed

移动声源速度值。
允许的值: - 任意数值。

别名键: - speed_meters_per_second: speed

speed_meters_per_second

这是 speed 的别名键。
允许的值: - 与 speed 相同。

声路径验证说明:
绝对路径、带盘符路径,以及路径穿越片段都会被拒绝。

运行时激活摘要:
如果 global = true,声源会在不进行区域/赛道段检查的情况下保持激活。
否则,激活与否取决于赛道段分配、区域跨度,以及起止触发条件。

6.6 值解析与标记规则

数值解析使用 invariant-culture,因此小数点必须写成 .
枚举解析不区分大小写,并且容忍标记文本中出现空格、连字符和下划线。
布尔值解析接受 1/0true/falseyes/noon/off

向量键必须严格写成三个由逗号分隔的浮点值(x,y,z)。
在严格部分中,未知键会被视为验证错误,除非键名以 metametadata 开头。
声路径安全规则会拒绝根路径、带盘符路径,以及路径穿越片段(即 ... 这样的路径组件)。
交叉引用验证会在解析结束后执行,用来确保被引用的天气 id、房间 id、赛道段 id 和声源 id 全部存在。

7. 房间混响模型与完整预设目录

7.1 混响参数含义

本节会用通俗语言解释每一个房间参数。

参数 它控制什么 增大后会发生什么
reverb_time_seconds 混响尾音在完全衰减前会持续多久。 空间听起来会更长、更有残留感。
reverb_gain 混响回传的整体强度。 相较于干声,反射声会更响。
hf_decay_ratio 高频在尾音中相对其他频段能保留多久。 高频内容会更久地保持明亮。
late_reverb_gain 后期、稠密尾音成分的电平。 后期混响主体会更强、更明显。
diffusion 早期与后期反射的稠密度/平滑度。 反射会显得更不离散、更融合、更平顺。
air_absorption 声音在空气中随距离造成的高频损失。 远处声音会损失更多亮度与清晰度。
occlusion_scale 障碍物削弱直达声的强度。 障碍物的遮挡效果会更强。
transmission_scale 声音穿过墙体/结构的程度。 你能听到更多穿透边界泄漏出来的声音。

7.2 完整内置房间预设

这张表为每个混响参数都单独使用一列,因此你可以直接对照各值,而不需要再去解读元组缩写。

类别 预设 声学特征 reverb_time_seconds reverb_gain hf_decay_ratio late_reverb_gain diffusion air_absorption occlusion_scale transmission_scale
户外环境 outdoor_open 非常开阔的平原,尾音极少。 0.35 0.08 0.85 0.08 0.20 0.65 0.35 0.75
户外环境 outdoor_field 开阔田野,比平原略厚一点。 0.45 0.10 0.82 0.10 0.25 0.62 0.38 0.72
户外环境 outdoor_urban 密集城市反射,回返能量更强。 0.90 0.22 0.70 0.24 0.45 0.48 0.55 0.52
户外环境 outdoor_suburban 混合型郊区反射,中等尾音。 0.75 0.18 0.74 0.20 0.38 0.50 0.48 0.58
户外环境 outdoor_forest 高频衰减更重,带有树木吸收感。 0.70 0.16 0.52 0.18 0.32 0.82 0.60 0.60
户外环境 outdoor_mountains 更大的反射空间,尾音更长。 1.80 0.34 0.52 0.36 0.42 0.42 0.55 0.52
户外环境 outdoor_desert 干燥开阔地形,反射主体较克制。 0.55 0.12 0.76 0.12 0.26 0.58 0.42 0.66
户外环境 outdoor_snowfield 开阔但高频更柔和,带雪地阻尼感。 0.90 0.20 0.62 0.24 0.34 0.70 0.45 0.62
户外环境 outdoor_coast 海岸线式开阔感,中等反射。 0.85 0.20 0.68 0.22 0.36 0.52 0.46 0.60
户外环境 outdoor_valley 开阔山谷感,回返更宽广。 1.60 0.30 0.56 0.34 0.46 0.46 0.58 0.52
隧道 tunnel_short 短隧道,反射清晰。 1.10 0.48 0.62 0.52 0.72 0.22 0.80 0.32
隧道 tunnel_medium 中等长度隧道,尾音更厚。 1.80 0.60 0.56 0.62 0.78 0.20 0.86 0.26
隧道 tunnel_long 长隧道,后期声场持续更久。 2.70 0.72 0.50 0.76 0.82 0.18 0.90 0.22
隧道 tunnel_concrete 硬质混凝土隧道特征。 2.10 0.66 0.54 0.70 0.80 0.20 0.88 0.24
隧道 tunnel_brick 砖砌隧道,音色更暖、尾音略短。 1.70 0.58 0.58 0.62 0.76 0.22 0.84 0.30
隧道 tunnel_metal 金属隧道,回返能量更明亮。 2.00 0.70 0.46 0.74 0.84 0.16 0.88 0.22
隧道 tunnel_stone 石质隧道,后期响应沉重。 2.40 0.68 0.50 0.72 0.80 0.18 0.90 0.24
下穿与桥下结构 underpass_small 紧凑下穿,回返快而稠密。 0.95 0.38 0.62 0.42 0.62 0.26 0.78 0.34
下穿与桥下结构 underpass_large 更大的下穿,反射列车更长。 1.35 0.46 0.56 0.52 0.68 0.24 0.82 0.30
下穿与桥下结构 overhang 局部遮盖,反射扩散中等。 0.75 0.30 0.66 0.34 0.56 0.28 0.72 0.38
下穿与桥下结构 bridge_truss 桥梁桁架腔体反应。 0.65 0.24 0.64 0.26 0.44 0.34 0.60 0.46
车库与停车空间 garage_small 小型车库,反射紧凑。 0.95 0.40 0.64 0.44 0.62 0.30 0.72 0.34
车库与停车空间 garage_medium 中型车库,尾音更宽。 1.30 0.48 0.60 0.52 0.68 0.28 0.74 0.30
车库与停车空间 garage_large 大型车库,后期声场更强。 1.80 0.56 0.58 0.60 0.72 0.26 0.76 0.28
车库与停车空间 parking_open 以开放为主的停车结构。 0.70 0.20 0.70 0.22 0.38 0.40 0.48 0.58
车库与停车空间 parking_covered 有顶停车区,反射更强。 1.20 0.44 0.60 0.48 0.64 0.28 0.72 0.34
车库与停车空间 parking_underground 地下停车场,包围感强且持续。 1.90 0.62 0.54 0.66 0.76 0.22 0.84 0.24
仓库与工业大厅 warehouse_small 小仓库,房间响应清晰。 1.10 0.38 0.62 0.42 0.66 0.30 0.70 0.34
仓库与工业大厅 warehouse_medium 中型仓库,尾音更饱满。 1.70 0.50 0.56 0.56 0.74 0.28 0.74 0.30
仓库与工业大厅 warehouse_large 大型仓库,衰减更长。 2.40 0.62 0.50 0.68 0.80 0.24 0.78 0.26
仓库与工业大厅 factory_hall 工业大厅,反射稠密。 2.20 0.60 0.48 0.66 0.78 0.24 0.80 0.26
仓库与工业大厅 machine_shop 机修车间,比仓库大厅更紧。 1.30 0.44 0.54 0.50 0.70 0.26 0.76 0.30
机库与交通站点 hangar_small 小型机库,反射宽阔。 2.00 0.56 0.54 0.60 0.76 0.24 0.72 0.30
机库与交通站点 hangar_large 超大型机库,混响场很长。 3.10 0.68 0.48 0.74 0.82 0.22 0.76 0.26
机库与交通站点 airport_terminal 航站楼走廊式反射风格。 1.80 0.52 0.58 0.58 0.74 0.28 0.66 0.36
机库与交通站点 subway_station 深层地铁站,封闭尾音很强。 2.30 0.64 0.50 0.70 0.80 0.22 0.84 0.24
机库与交通站点 rail_station 大型火车站,但没有地铁站那么封闭。 1.90 0.54 0.56 0.60 0.74 0.26 0.72 0.32
走廊、地下室与封闭空间 corridor_short 短走廊,反馈迅速。 0.85 0.36 0.62 0.40 0.58 0.30 0.72 0.34
走廊、地下室与封闭空间 corridor_long 长走廊,反射被拉长。 1.40 0.50 0.56 0.56 0.68 0.26 0.80 0.28
走廊、地下室与封闭空间 stairwell_concrete 混凝土楼梯井,后期回返扎实。 1.60 0.54 0.54 0.58 0.70 0.26 0.78 0.28
走廊、地下室与封闭空间 basement_low 低矮地下室,中等封闭尾音。 1.10 0.44 0.58 0.48 0.66 0.28 0.76 0.30
走廊、地下室与封闭空间 basement_large 大型地下室,后期能量更重。 1.90 0.58 0.52 0.64 0.76 0.24 0.82 0.26
走廊、地下室与封闭空间 bunker 厚重的封闭地堡响应。 2.10 0.64 0.46 0.70 0.80 0.20 0.90 0.20
走廊、地下室与封闭空间 vault 高度封闭的金库特征。 2.60 0.72 0.42 0.78 0.84 0.18 0.92 0.18
大厅、竞技场与体育场 hall_small 小型大厅,反射连贯。 1.10 0.40 0.64 0.44 0.70 0.30 0.68 0.34
大厅、竞技场与体育场 hall_medium 中型大厅,密度更饱满。 1.70 0.52 0.58 0.56 0.78 0.28 0.72 0.30
大厅、竞技场与体育场 hall_large 大型大厅,空间尾音更长。 2.70 0.62 0.50 0.66 0.82 0.24 0.78 0.26
大厅、竞技场与体育场 arena_indoor 室内大场馆,扩散度高。 3.00 0.66 0.48 0.72 0.84 0.24 0.70 0.32
大厅、竞技场与体育场 stadium_open 开放式体育场,封闭感更轻。 1.50 0.45 0.60 0.50 0.70 0.40 0.40 0.60
大厅、竞技场与体育场 stadium_closed 封闭式体育场,后期声场延展更明显。 2.80 0.64 0.50 0.70 0.82 0.28 0.68 0.34
房间与录音室 room_small 小房间,响应短且聚焦。 0.70 0.30 0.70 0.32 0.62 0.36 0.60 0.40
房间与录音室 room_medium 中等房间,主体与尾音平衡。 1.10 0.40 0.62 0.42 0.70 0.30 0.62 0.34
房间与录音室 room_large 大房间,尾音拖得更久。 1.80 0.50 0.54 0.54 0.76 0.26 0.68 0.30
房间与录音室 studio_dry 干声录音室,尾音很短。 0.35 0.12 0.78 0.14 0.40 0.50 0.40 0.70
房间与录音室 studio_live 现场录音室风格,空间感更明显。 0.90 0.34 0.66 0.38 0.66 0.34 0.58 0.44
房间与录音室 broadcast_booth 非常干的播音间,控制极强。 0.28 0.08 0.82 0.10 0.30 0.58 0.45 0.70
教堂、洞穴、峡谷与下水道 church_small 小型教堂,尾音很明显。 2.40 0.56 0.46 0.60 0.82 0.26 0.72 0.30
教堂、洞穴、峡谷与下水道 church_large 大型教堂,混响绽放更长。 3.80 0.70 0.40 0.76 0.86 0.22 0.78 0.24
教堂、洞穴、峡谷与下水道 cathedral 非常大的神圣大厅,衰减极长。 5.40 0.78 0.34 0.84 0.90 0.20 0.82 0.20
教堂、洞穴、峡谷与下水道 cave_small 小型洞穴,封闭反射稠密。 2.60 0.62 0.46 0.66 0.74 0.20 0.86 0.24
教堂、洞穴、峡谷与下水道 cave_large 大型洞穴,尾音长而偏暗。 4.50 0.78 0.34 0.84 0.84 0.16 0.92 0.16
教堂、洞穴、峡谷与下水道 cave_ice 冰洞风格,回返明亮且拖尾更久。 3.80 0.72 0.40 0.80 0.80 0.24 0.86 0.22
教堂、洞穴、峡谷与下水道 canyon_narrow 狭窄峡谷,回返方向性明显。 2.10 0.54 0.46 0.58 0.52 0.34 0.64 0.42
教堂、洞穴、峡谷与下水道 canyon_wide 宽峡谷,扩散更广、封闭感更弱。 2.90 0.60 0.44 0.64 0.48 0.36 0.56 0.48
教堂、洞穴、峡谷与下水道 sewer_brick 砖砌下水道,潮湿而封闭的尾音。 2.10 0.62 0.50 0.68 0.78 0.22 0.86 0.22
教堂、洞穴、峡谷与下水道 sewer_concrete 混凝土下水道,反射硬朗。 2.40 0.68 0.46 0.74 0.82 0.20 0.88 0.20

8. 完整示例 TSM 赛道文件

[meta]
name = Demo Accessible Track
version = 1
weather = clear
ambience = noambience

[weather:clear]
kind = sunny
longitudinal_wind_mps = 0
lateral_wind_mps = 0
air_density = 1.225
drafting_factor = 1
temperature_c = 22
humidity = 0.45
pressure_kpa = 101.325
visibility_m = 20000
rain_gain = 0
wind_gain = 0
storm_gain = 0

[weather:storm_edge]
kind = storm
longitudinal_wind_mps = 4
lateral_wind_mps = 8
air_density = 1.24
drafting_factor = 1
temperature_c = 17
humidity = 1
pressure_kpa = 99.8
visibility_m = 3500
rain_gain = 0.2
wind_gain = 0.4
storm_gain = 1.0

[room:open_day]
room_preset = outdoor_open

[room:tunnel_a]
room_preset = tunnel_medium
reverb_gain = 0.62
late_reverb_gain = 0.65

[sound_ambient:birds]
path = Audio/birds_loop.ogg
loop = true
volume = 0.5
spatial = false

[sound_random:wind_gusts]
variant_paths = Audio/wind_gust_1.ogg, Audio/wind_gust_2.ogg, Audio/wind_gust_3.ogg
random_mode = perarea
loop = true
volume = 0.4
spatial = true
allow_hrtf = true
fade_in = 0.15
fade_out = 0.15
crossfade_seconds = 0.5
start_area = s2
end_area = s5

[segment:s1]
type = straight
surface = asphalt
noise = none
length = 300
width = 10
room = open_day
sound_sources = birds

[segment:s2]
type = easy_right
surface = asphalt
noise = crowd
length = 220
room = open_day
sound_source_ids = wind_gusts

[segment:s3]
type = hard_right
surface = asphalt
noise = none
length = 180
room = tunnel_a
weather = storm_edge
weather_transition_seconds = 2.5

[segment:s4]
type = straight
surface = asphalt
noise = jet
length = 260
room = tunnel_a

[segment:s5]
type = left
surface = asphalt
noise = none
length = 240
room = open_day
weather = clear
weather_transition_seconds = 1.5

9. 验证与故障排查

在构建运行时对象之前,赛道加载会先经过一个严格的验证阶段。错误会直接阻止加载;警告则允许继续加载,但某些值可能会被钳制规则调整。

常见的硬失败以及直接修复方法:

失败项 为什么会发生 修复方法
缺少默认天气配置 meta.weather 为空,或指向了未知 id meta 中定义 weather = some_id,并添加 [weather:some_id] 部分
部分 id 重复 同一家族中的两个部分复用了同一个 id 重命名 id,确保每个 segmentweatherroomsound id 都唯一
未知枚举标记 值文本无法映射到受支持的枚举标记/整数 使用本指南中的合法标记,或合法的数字枚举值
严格部分中出现未知键 键名拼写错误,或该键根本不受支持 修正拼写;自定义标签请放在 meta* / metadata* 前缀下
未知引用 id 赛道段或声音引用了不存在的 id 添加缺失的目标部分,或修正引用 id 文本
无效的声路径 使用了绝对路径、带盘符路径或路径穿越 只使用赛道相对路径,例如 Audio/wind.ogg
无效向量 位置值不是严格的 x,y,z 浮点格式 严格写成由逗号分隔的三个浮点值

需要特别注意的非致命行为:

10. 实用创作流程

一个稳定的工作流,是把制作分成四轮,并且每轮都测试,而不是一口气把所有系统一次性写完。

第一轮只做几何:meta、一个天气配置,以及包含 typelengthsurfacewidth 的赛道段。先确认节奏、弯道流动感和圈速手感。

第二轮做天气过渡:加入额外的天气配置,然后只在你确实想要发生天气切换的地方,为赛道段添加 weatherweather_transition_seconds。确认过渡是否平滑,并且是否发生在预期的赛道段边界上。

第三轮做声学:为隧道、封闭结构等特定区域加入房间预设或房间部分。如果需要局部微调,请优先使用赛道段级房间覆盖,而不是复制大量房间部分。

第四轮做声源:先从一个路径已知正确的简单声源开始,然后再逐步加入空间化行为、区域触发和随机变体。验证来自赛道段的每一个声源 id 引用,以及来自声触发器的每一个区域 id 引用。

最好再另外保留一份纯文本顺序说明,用来描述赛道段顺序、距离和设计意图。当行为不对时,把这份顺序说明与运行时表现一对照,就能更容易判断问题是出在几何、天气 id、房间选择,还是声触发引用上。