Roads(道路)
道路网格(Mesh)的设置
汽车导航系统使用的是带有相交掩码的特殊边界。 边界(border)可被描述为表面,或是3D对象。 通常,每种辅助相交表面(左,右,中)都是道路网格(mesh)的一部分。 其在如下情况出现时会被从场景中隐去:
- 给它分配了透明材质。
- 其视窗掩码被设为0x0。
左边界的相交掩码值为0х00000004,右边界的相交掩码值为0х00000008。
下图展示了辅助表面的例子,这些表面是专为实现具有双向通车功能的双向车道而设置的。
汽车会对道路和行车方向执行搜索,而行人则会凭借相交射线对人行道执行搜索。 通车车道的数量会被自动计算,不过通车车道的宽度是恒定值(3.75米)。 您可在路径下文件data/projects/driving/scripts/driving_consts.h(LINE_WIDTH常量)中对其重新定义。
下图展示了汽车的行车方向检测的逻辑:
每个对象在移动时都会间歇地投射出2条射线:一条投射到左边,另一条投射到右边。 如果左边的射线与掩码为0х00000008的边界相交,右边的射线与掩码为0х00000004的边界相交,我们就能确定行车方向,通车车道的数量,以及对象正沿其运动的车道的数量。
您也可以设置汽车或行人会被自动放置其上的表面。 要想这么做,须设置spawn_surface属性,外加Spawn Car(生成汽车)参数,或是Spawn Pedestrian(生成行人)参数。
这样的表面也可被组织进节点引用,并在之后被用来构成不同的道路系统。
交叉路口的设置
交通模拟的一个最重要问题是交叉路口的相交。 要想定义交叉路口处的运动轨迹,系统就需要创建特殊的曲线。 像道路网格一样,交叉路口也需要带有相交掩码的边界,这样就能定义入口道路和出口道路了。
交叉路口设置的下一步是创建其大小比交叉路口自身稍大的WorldTrigger。 要想定义入口道路和出口道路,就应具有放置在每个入口处的特殊网格。 这些网格应是WorldTrigger的子节点。
沿Y轴的入口网格的方向应 exit the crossroad(使用的本地坐标)。 沿X轴的宽度(使用的本地坐标)定义了道路的宽度,该宽度可通过更改Scale X参数来调整。
这些网格应分配有"junction_entry"属性,并且如果交叉路口是不受控制的,那行车优先级就应被指定为Priority(优先级)参数。 该参数值越高,此入口的行车优先级也就越高。
在仿真时,这些网格将被禁用;它们的轴心将成为入口的停车线。 如果您需要移动停车线,那就可以使用"junction_entry"属性的Calculate Stop Line(计算停车线)参数。 所以,您更改Scale Y参数就可以将停车线移远或拉近。
如果所有方面都正确设置了,那在初始化时交叉路口将会自动定义如下参数:
- 交叉路口处的行车方向(根据边界和相交射线确定)。
- 通车车道的数量。
- 入口优先级和出口优先级。
- 汽车的运动曲线。
要想限制交叉路口的行车速度,可使用如下交叉路口参数:
- Forward Speed(前进速度) - 用来限制向前行车时的速度。
- Turn Speed(转弯速度) - 用来限制转弯时的速度。
环岛
环岛是一组出自圆圈的各个出口所组成的T型交叉口。 要想指定交叉路口是环岛,可启用Circular(循环)选项。 环岛与交叉路口相似,唯一不同的是后者有出路口规则。
交通信号灯
交通信号灯是交叉路口的行车规程中的重要部分。 这些信号灯能动态更改相交优先级。
从Entity类继承来的被称为TrafficLight的特殊类负责处理交通信号灯。 它可被绑定给如下节点:
- 单个ObjectMeshStatic。
- NodeReference,其会让一个ObjectMesh作为根节点。
- DummyNode,其会让不同的ObjectMesh对象作为子节点(前提是交通信号灯包含多个网格)。
负责交通信号灯的信号的表面应分配有"traffic_light_base"属性。 该属性拥有3参数:
- Material on(材质开启) - 指交通信号灯亮起时使用的材质。
- Material off(材质关闭) - 指交通信号灯熄灭时使用的材质。
- Light type(信号类型) - 指包含标记列表的字符串。 该字符串的组成可以是这样:"%state_name,%state_name,...,%state_name",其中的%state_name指如下的某一个信号类型:
- R - 指红灯信号。
- Y - 指黄灯信号,一直闪动。
- G - 指绿灯信号。
- GF - 指闪动的绿灯信号。
- GL - 指绿色向左箭头。
- GLF - 指闪动的绿色向左箭头。
- GR - 指绿色向右箭头。
- GRF - 指闪动的绿色向右箭头。
- PR - 指给行人的红灯信号。
- PG - 指给行人的绿灯信号。
例如,"light type"="GF,G"意味着表面会在交通信号灯具有G标记或GF标记的情况下被启用。
交通信号灯只能由交叉路口控制。
带交通信号灯的交叉路口
要想创建带交通信号灯的交叉路口,您就需要为每个交叉路口的入口都设置一个交通信号灯。 请注意,入口网格和交通信号灯都必须让NodeDummy作为父节点;该NodeDummy应成为交叉路口WorldTrigger的一个子节点。
当汽车即将驶达某个交叉路口时,便会有一个交通信号灯(前提是存在)供这个交叉路口定义。 这时汽车将根据交通信号灯的信号来做进一步移动的决定。
交叉路口处的每一个交通信号灯都应拥有一个索引编号(以0开头的编码),这样,交叉路口便会根据给定规则来设置交通信号灯的信号。 该规则存储在文本文件中,并会被作为Traffic Light Rule(交通信号灯规则)设置给Entity Fields(实体字段)中的交叉路口(Junction类)。 该文件拥有如下格式:
10 | "R" | "G" | "R" | "G" |
2 | "R" | "GF" | "R" | "GF" |
2 | "R" | "Y" | "R" | "Y" |
5 | "R" | "R,GL" | "R" | "R,GL" |
2 | "R" | "R,GLF" | "R" | "R,GLF" |
2 | "R" | "Y" | "R" | "Y" |
10 | "G" | "R" | "G" | "R" |
2 | "GF" | "R" | "GF" | "R" |
2 | "Y" | "R" | "Y" | "R" |
5 | "R,GL" | "R" | "R,GL" | "R" |
2 | "R,GLF" | "R" | "R,GLF" | "R" |
2 | "Y" | "R" | "Y" | "R" |
每一行的第1个值定义了信号要给交叉路口设置的时间间隔。 例如,按照第一行的示意,前10秒内四个交通信号灯将使用这样的信号:第一个和第三个 - 红灯信号("R"状态);第二个和第四个 - 绿灯信号("G"状态)。
10秒之后,所有交通信号灯的状态都将跳变为第二行的状态,即:2秒内交通信号灯将使用这样的信号:第一个和第三个 - 红灯信号("R"状态);第二个和第四个 - 闪动的绿灯信号("GF"状态)。
2秒之后,所有的状态都将跳变为第三行的状态,等等。
规则文件中列的数量应等于交叉路口的交通信号灯的数量。
人行横道
为了使行人可以穿越道路,您需要在用作人行横道的地方放置一WorldTrigger。 该WorldTrigger应分配有Crosswalk实体,这样,此区域就将成为不受管制的人行横道,行人就能从中穿行,汽车也会给行人让道。
此外,您也可以设置可视节点,像带有斑马线或专用标志的印花(decal)。
交叉路口处的受管制的人行横道
要想在交叉路口处创建受管制的人行横道,您就需要执行如下操作:
- 添加具有所需大小的WorldTrigger并将其放置在所需位置。
- 让其成为交通信号灯节点的子节点。
交通信号灯会识别人行横道,并会在交通信号灯的状态为"PG"(给行人的绿灯信号)时让行人穿行,或在状态为"PR"(给行人的红灯信号)时禁止行人穿行。
设限的特殊区域
与人行横道,交通信号灯和行车优先级一起存在的还有一些设限的特殊可调区域,例如:限速区,禁止超车区等等。
对于这些区域,我们使用了一种从Entity类继承来的特殊类RuleArea。 它被绑定给了WorldTrigger。 当有汽车驶入WorldTrigger时,就会将特殊规则或限制应用给它。 您所需要做的仅仅是手动展开类并调用所需函数。