公交路线

本文将介绍如何创建公交路线,即由多个公交车站组成的公交行驶路径。

文件和文件夹设置

  1. 在你想要修改的关卡目录下创建两个新文件夹:

    • scenarios
    • bus lines

    例如,如果你想修改 “smallgrid” 关卡,请在 ..\levels\smallgrid\ 路径下创建上述文件夹。

如果这些文件夹已存在于你正在修改的关卡目录下,可以跳过此步骤。

  1. scenarios 文件夹内,新建一个名为 “bus” 的文件夹。

    bus 文件夹内,你需要创建一个 bus_level.json 文件。该文件的内容如下所示:

[
    {
        "name": "bus_level",
        "description": "bus_level",
        "authors": "Your Name",
        "introType": "none",
        "difficulty": "22 ",
        "date": 1494325025,
        "levelObjects": {
            "tod" : {
                "time" : 0.11,
                "play" : false
            }
        },
        "vehicles": {
            "scenario_player0": {
                "playerUsable": true,
                "startFocus": true
            },
            "*": {"playerUsable": false}
        },
        "radiusMultiplierAI": 2,
        "extensions": ["busdriver"],
        "busdriver": {
            "routeID": "1",
            "variance": "a"
        },
        "statistics":
        {
            "disableEndUI": true
        }
    }
]
  • 修改前两个变量 "name""description",将关卡部分替换为你所编辑关卡的名称。例如,如果你修改的是 “Utah” 关卡,可以使用 bus_utah.json 作为文件名。需要注意的是,这个命名规则不是强制性的。在本例中,smallgrid 关卡可以使用 "bus_grid.json" 作为名称。
  • "busdriver" 对象应包含默认要游玩的路线,因此请根据实际情况修改 "routeID""variance" 字段。
如果 bus 文件夹中已经有对应的 bus 场景 json 文件,可以跳过此步骤。

  1. 在你的 buslines 文件夹中创建一个简单的文本文件,内容请参考下方的模板。

保存文件时将其命名为 levelName.buslines.json,请确保该 .json 文件名是唯一的。

{
    "version": 1,
    "routes":[
        {"routeID":"1",
            "variance":"a",
            "direction":"Rexoni Diner",
            "routeColor": "#3b9c00",
            "vehicle" : {
                "model": "citybus",
                "config": "base"
            },
            "tasklist":[
                "tmpl_bs_07",
                "tmpl_bs_13",
                "tmpl_bs_02",
                "tmpl_bs_23",
                "tmpl_bs_26",
            ],
            "spawnLocation": {
                "pos": {"x": -613.572,"y": 199.223,"z": 113.173},
                "rotAngAxisF": {"x": 0,"y": 0,"z": 1,"w": 224.173}
            },
            "requiredWaypoints":{
                "wcu_bs_29":{
                    "wp":["wcu_cp_agave"],
                    "failmsg":"You got too far-off the route" },
                "wcu_bs_27":{
                    "wp":["wcu_cp_hwy"],
                    "failmsg":"You got too far-off the route" }
            },
            "navhelp":{
                "wcu_bs_13":["wpTown_16","Bridge36_3","Bridge36_1"],
                "wcu_bs_26":["bs_raceTrack_1","Bridge4_B1","Bridge4_A1","Bridge4_A2","countryside_road_1","countryside_road_2"],
                "wcu_bs_29":["Junction_mountain_A","Bridge1_B"],
                "wcu_bs_27":["countryside_road_3","Bridge2_A1","Bridge2_A2","Bridge2_A3","Bridge17_A","Bridge17_B","Bridge17_E"],
                "wcu_bs_28":["countryside_road_4"],
            },
            "previews":[
                "01_RexDiner.png"
            ]
        },
        {"routeID":"2",
            "variance":"a",
            "direction":"Khaki Bay",
            "routeColor": "#fff200",
            "tasklist":[
                "tmpl_bs_04",
                "tmpl_bs_01",
                "tmpl_bs_05_b",
                "tmpl_bs_14_b",
                "tmpl_bs_19_b",
                "tmpl_bs_25_b",
                "tmpl_bs_24_b",
                "tmpl_bs_27_b",
                "tmpl_bs_21",
                "tmpl_bs_17"
            ],
            "vehicle" : {
                "model": "citybus",
                "config": "base"
            },
            "spawnLocation": {
                "pos": {"x": -337.572,"y": 605.564,"z": 75.0979},
                "rotAngAxisF": {"x": 0,"y": 0,"z": 1,"w": 135.337}
            },
            "requiredWaypoints":{
                "wcu_bs_27":{
                    "wp":["wcu_cp_hrzn"],
                    "failmsg":"You got too far-off the route" }
            },
            "navhelp":{
                "wcu_bs_21":["Bridge17b_A"],
                "wcu_bs_17":["tennis_1","tennis_2"],
            },
            "previews":[
                "02_KhahkiBay.png"
            ]
        },
    ]
}

JSON 指南

以下是在创建 levelName.buslines.json 文档时的一些实用建议。

.json 文件由一个 JSON 对象组成,包含 2 个变量: “version” 表示公交线路文件的版本号,是一个数字; “routes” 是一个由 JSON 对象组成的数组,每个对象都定义了一条公交线路。每个公交线路对象包含:

  • routeID 必须为字符串类型,虽然实际是数字,例如:"routeID":"101"
  • direction 理想情况下每条线路应有两个方向:一个从A到B,另一个从B到A。该变量仅用于显示,建议使用易于识别的命名方式。
  • variance 是用于描述该线路具体变体的字符串。当一个线路ID有多个变体时,该字段会被内部使用。
  • routeColor 是一个代表线路颜色的 HTML 十六进制字符串。
  • vehicle 表示所用车辆。请将 model 设为 citybusconfig 设为 base
  • tasklist 是一个由字符串组成的json数组(每项之间不要有空格),用于表示公交车站的触发器。
  • requiredWaypoints 是一个可选的json对象,指明车辆必须通过的强制点,以及未通过时的提示信息。每个必经点都是一个对象,包含2个变量:一个是该点的字符串ID数组,一个是未通过时显示的失败提示信息。
  • spawnLocation 是一个包含两个对象的json对象,分别为 "pos"rotAngAxisF,用于表示车辆的起始位置和朝向。旋转对象有两种类型:
    • rot:四元数格式的旋转,由LUA脚本给出
    • rotAngAxisF:“角度-轴”格式的旋转,通常在编辑器中使用。x, y, z 表示旋转轴,w 表示旋转角度(度)。推荐使用此方式,因为更易操作。
  • navhelp 是一个可选的json对象,包含以需要导航帮助的车站ID命名的数组。每个数组中包含该导航箭头需要通过的路径点(字符串)。
  1. 根据上一步的要求,对 levelName.buslines.json 文档中的变量名和值进行重命名和修改。

  2. 保存文件。

初始生成点(Spawnpoints)

  1. 启动游戏并进入 游玩 > 公交线路 > 选择地图。然后,选择需要修改的地图(即新建文件夹的地图),并选择一个行驶方向(例如“Rexoni Diner”)。如果车辆出生在空中或地下,不要担心,后续步骤会调整出生点。

  2. 按下 Shift+C 以切换 自由相机(Free Camera)。使用导航键 W A S D 在地图中移动,直到你选择并到达理想的起点位置。尽量使视角靠近地面。

  3. 按下 F11 打开 世界编辑器(World Editor)

  4. 点击 相机(Camera) 选项卡,然后点击 将玩家放置到相机处(Place Player at Camera)

  1. 点击车辆以显示车辆的标记。如果标记未显示,请在**场景树(Scene Tree)编辑工具中查找(如果没有该工具,可以从窗口(Window)**标签添加)。

    向下滚动到 ScenarioObjectsGroup 文件夹。在此文件夹下,选择 scenario_player0,这样就可以选中你的车辆并显示标记。

  1. 你可以在**属性检查器(Inspector)**编辑工具的“变换(Transform)”标签中直接输入位置和旋转值,或者使用*平移(Translate)旋转(Rotate)*编辑工具分别设置。

  1. 当你对车辆的起始位置和朝向满意后,从**属性检查器(Inspector)**的“变换(Transform)”标签中复制这些数值,填入你的 levelName.buslines.json 文件的 spawnLocation 字段中。

  2. 保存文件。

公交车站(Bus stops)

  1. 场景树(Scene Tree) 中,点击 ScenarioObjectsGroup 文件夹,然后点击场景树窗口左上角的 新建文件夹(New folder) 图标。

将新文件夹命名为 busstops,并打开该文件夹。

  1. 回到游戏中,按下 Shift+C 切换 自由相机(Free Camera) 并返回至车辆的相机视角。随后在地图中移动,直到到达你希望设置公交车站的位置。

  2. 世界编辑器工具栏(World Editor Toolbar) 中:

  • 点击 添加对象(Add Object) 按钮
  • 在下方出现的工具栏中,点击 BeamNG 图标
  • 点击 LUA触发器(LUA Trigger) 图标
  • 在三维视图(3D view)中任意位置点击放置

这将在你在三维视图(3D 视图)中点击的位置创建一个 LUA触发器(LUA Trigger),该对象也会出现在场景树列表中。

LUA 触发器只有在被选中时才可见,除非在 可视化(Visualization) 菜单中启用了 触发器(Triggers) 选项(可以通过 窗口(Window) 按钮访问该菜单)。

  1. 按照 步骤 11 所述,修改该触发盒的位置、旋转和缩放。

    对于触发器的缩放参数,将 “x” 值设为能容纳车辆宽度,将 “y” 值设为能容纳车辆长度。

由于只有当车辆完全进入触发盒时才会激活该触发器,请设置盒子的尺寸,使其足够大,可以包含车辆。建议让包围盒稍微深入地面以下。

  1. 当调整好触发器的尺寸和位置后,前往**世界编辑器(World Editor)**的 **属性检查器(Inspector)**窗口。从你的 levelName.buslines.json 文件中的 tasklist 复制该触发器的唯一标识符(例如:tmpl_bs_07),并粘贴到 Inspector 面板中名称(name)选项处。

请注意,这个标识符必须是一个不包含空格的字符串,如“步骤3”中所述。建议保持名称简短。

  1. 选中触发器后,在 属性检查器(Inspector)Trigger 部分,做如下设置:
    • TriggerType > Box
    • TriggerMode > Contains
    • TriggerTestType > Bounding box
    • TickPeriod > 1000

  1. 完成上述设置后,在 属性检查器(Inspector) 窗口中向下滚动,找到 动态字段(Dynamic Fields) 部分。

  1. 在 Dynamic Fields 中输入 type,点击 Add(添加),然后将其数值设置为 busstop

  1. 再添加一个名为 stopName 的动态字段,并输入公交站的实际名称,这个名称将在游戏中显示(例如:Fleet Street)。

  2. 对于每一个你希望新建的公交站,都请重复 步骤 15 至 22

  3. 保存时需要更多细节
上一次修订: 六月 22, 2026

还有其他问题?

加入我们的 Discord 服务器
Our documentation is currently incomplete and undergoing active development. If you have any questions or feedback, please visit this forum thread.