BeamNG 能够实现车辆改装的其中一个重要机制,就是部件/插槽系统。
如果你曾经使用过部件选择器(Part Selector),你会发现车辆包含多个部件,每个部件通常有多个选项,并且这些选项分为不同的层级,有些部件选项是否可用,还取决于你前面所选择的部件。
你在部件选择器中看到的所有内容,都是在每个组件的 jbeam 文件里定义的。下面是一个简要示例:
"autobello_suspension_F": { // 组件的内部名称
"information":{
"authors":"BeamNG", // 在部件选择器中显示的作者名称
"name":"Trailing Link Front Suspension", //部件名称
"value":400,
},
"slotType":"autobello_suspension_F",// 插槽类型
"slots":[ // 插槽列表
["type", "default", "description"],
["autobello_brake_F","autobello_brake_F", "Front Brakes"],
["wheel_F_4","steelwheel_11b_13x5_F", "Front Wheels"],
["autobello_spring_F","autobello_spring_F", "Front Springs"],
["autobello_steering","autobello_steering", "Steering"],
],
},
每个部件都有一个内部名称,在该部件 jbeam 文件的第一行定义。这个名称会被游戏用来引用该部件,但用户不可见。确保这个名称唯一非常重要,否则会引发部件互相覆盖等问题。
信息部分用于展示该部件的一些基本信息,包括会在部件选择器中显示的名称。
每个部件还有一个 slotType (插槽类型),用于标识该部件在车辆中的安装位置。
插槽类型允许你为同一个插槽类型配置多个部件作为备选方案,所有具有相同“插槽类型”的部件会在部件选择器中作为同一部件的不同选项展示。
有一种特殊的插槽类型叫做“main”,它代表整车的基础组件,标识该部件为车辆的“根”部件,并且会是游戏加载的第一个部件。每辆车只能有一个这个插槽类型的部件。
slots 部分用于定义哪些部件是当前部件的“子部件”,这些子部件通过 slotType 进行区分。例如在前悬挂的例子中,你会找到前刹车、车轮、避震、转向等内容。
最终的结果就是一个组件选择树,最上方是“main”主部件,下面有多层“子”部件。
在游戏中你可能已经注意到,每辆车都带有预设的配置,包括不同的套件版本、越野版、赛车版等等。
这些预设其实很简单,只需要用到所谓的“配置文件”。下面就是打开一个配置文件后能看到的一个简单示例:
{
"parts":{
"coupe_enginemounts":"coupe_enginemounts_heavy",
"coupe_oilpan_I4":"coupe_oilpan_I4_race",
"coupe_engine_ecu":"coupe_engine_ecu_race",
"coupe_engine_internals":"coupe_engine_internals_stage2",
"coupe_taillight_L":"coupe_taillight_L",
"paint_design":"coupe_skin_nomi",
...
}
"vars":{
"$trackoffset_R":0.02,
"$trackoffset_F":0.025,
"$lsdpreload_R":125,
...
},
配置文件本质上是一个包含各个插槽及其对应所用部件的 json 表。如果某个插槽未在配置文件中指定,则会使用默认部件。
配置文件还可以定义各种变量 所使用的值。
除了配置文件,你经常还会看到一个 info 文件,它用于描述该配置在车辆选择器中显示的各种信息,以及预览缩略图。
通过巧妙地运用一些 Jbeam 的高级机制,比如插槽变量 和函数 ,可以让两个不同的 Jbeam 组件由同一份代码定义,并能同时选择。要实现这一点,父级插槽中需要引入一个字符串变量,如下所示:
"slots": [
["type", "default", "description"],
["reusable_part_slot1", "", "Slot 1", {"nodeMove":{"x": 2,"y":0,"z":0}, "variables":{"$prefix":"a"}}],
["reusable_part_slot2", "", "Slot 2", {"nodeMove":{"x":-2,"y":0,"z":0}, "variables":{"$prefix":"b"}}],
],
然后在可复用部件本身中,slotType 应该是一个同时适用于上述两种类型的表,并且部件中所有唯一的字符串(比如 group 名称和节点名称)都需要与变量字符串进行拼接,例如:
"reusable_part": {
"information":{
"authors":"BeamNG",
"name":"Reusable Part",
},
"slotType" : ["reusable_part_slot1", "reusable_part_slot2"],
"nodes": [
["id", "posX", "posY", "posZ"],
{"nodeWeight":1.0},
{"collision":true},
{"selfCollision":true},
{"group":"$=$prefix..'_group'"},
["$=$prefix..'1'", 1,-1, 0],
["$=$prefix..'2'",-1,-1, 0],
["$=$prefix..'3'",-1, 1, 0],
["$=$prefix..'4'", 1, 1, 0],
["$=$prefix..'5'", 0, 0, 2],
{"group":""},
],
"beams": [
["id1:", "id2:"],
{"beamPrecompression":1, "beamType":"|NORMAL", "beamLongBound":1, "beamShortBound":1},
{"beamSpring":461000,"beamDamp":140},
{"beamDeform":40000,"beamStrength":100000},
["$=$prefix..'1'", "$=$prefix..'2'"],
["$=$prefix..'1'", "$=$prefix..'3'"],
["$=$prefix..'1'", "$=$prefix..'4'"],
["$=$prefix..'2'", "$=$prefix..'3'"],
["$=$prefix..'2'", "$=$prefix..'4'"],
["$=$prefix..'3'", "$=$prefix..'4'"],
["$=$prefix..'1'", "$=$prefix..'5'"],
["$=$prefix..'2'", "$=$prefix..'5'"],
["$=$prefix..'3'", "$=$prefix..'5'"],
["$=$prefix..'4'", "$=$prefix..'5'"],
],
"triangles": [
["id1:","id2:","id3:"],
["$=$prefix..'1'", "$=$prefix..'2'", "$=$prefix..'3'"],
["$=$prefix..'3'", "$=$prefix..'4'", "$=$prefix..'1'"],
["$=$prefix..'1'", "$=$prefix..'5'", "$=$prefix..'2'"],
["$=$prefix..'2'", "$=$prefix..'5'", "$=$prefix..'3'"],
["$=$prefix..'3'", "$=$prefix..'5'", "$=$prefix..'4'"],
["$=$prefix..'4'", "$=$prefix..'5'", "$=$prefix..'1'"],
],
},
你还可以定义额外的插槽Boolean变量,并将它们与 Disable Modifier 一起使用,根据 slotType 切换 Jbeam 文件中的不同行。
这篇文章对你有用吗?