UE5 Mass交叉路口交通规则

交通灯控制行人和车辆的大致原理

对于行人是通过给行人的lane添加FZoneGraphTag(CloseLaneTag、WaitingLaneTag)来告知AI哪些道路当前禁止行走。车辆则是通过修改车道数据的bIsOpen来表示是否开放,进而影响车对道路的选择(详细代码在UMassTrafficChooseNextLaneProcessor::Execute)。
UMassTrafficIntersectionSpawnDataGenerator主要负责交叉路口信息搜集、红绿灯周期的创建(讲道理应该离线生成,目前是运行时执行)。目前一共有四种周期模式:两岔路口、标准十字路口、其他有红绿灯路口、stop-sign路口(无红绿灯)。
UMassTrafficUpdateIntersectionsProcessor负责红绿灯周期的切换逻辑。

前置知识

Mass基础可以参看:UE5 Mass初体验

MassSpawner

Entity生成器,主要职责包括:生成的总数量、出生点位的生成(FMassSpawnDataGenerator负责)、Entity配置(有哪些Fragment,通过UMassEntityConfigAsset进行配置)、各类Entity数量占比。
场景中需要放置一个MassSpawner用来生成所有的交通路口Entity,并且需要在MassSpawner的SpawnDataGenerators中需要配置UMassTrafficIntersectionSpawnDataGenerator。

ZoneGraph

路网,包括人行道、机动车道。一个AZoneShape对应一个Zone。FZoneGraphBuilder负责将场景中的AZoneShape转换成数据存储到FZoneGraphStorage。具体构建代码详见:void FZoneGraphBuilder::Build(AZoneGraphData& ZoneGraphData)。
ZoneGraph相关文档:ZoneGraph Quick Start Guide
在这里插入图片描述

USTRUCT()
struct ZONEGRAPH_API FZoneGraphStorage  // ZoneGraph的数据存储
{
    GENERATED_BODY()
    void Reset();
    const FZoneData& GetZoneDataFromLaneIndex(int32 LaneIndex) const { return Zones[Lanes[LaneIndex].ZoneIndex]; }
    // 所有的zone
    UPROPERTY()
    TArray<FZoneData> Zones;
    // 所有的Lane数组,Zone会有保存自身所属Lane的起始和结束索引
    UPROPERTY()
    TArray<FZoneLaneData> Lanes;
    // 所有Zone的边界点的数组
    UPROPERTY()
    TArray<FVector> BoundaryPoints;
    // 所有Lane的路点。
    UPROPERTY()
    TArray<FVector> LanePoints;
    // All the lane up vectors, referred by lanes.
    UPROPERTY()
    TArray<FVector> LaneUpVectors;
    // 所有Lane的切线
    UPROPERTY()
    TArray<FVector> LaneTangentVectors;
    // 所有lane的距离进度
    UPROPERTY()
    TArray<float> LanePointProgressions;
    // 所有Lane之间的连接信息
    UPROPERTY()
    TArray<FZoneLaneLinkData> LaneLinks;
    // 所有Zone的Bounding box.
    UPROPERTY()
    FBox Bounds = FBox(ForceInit);
    // BV-Tree of Zones
    UPROPERTY()
    FZoneGraphBVTree ZoneBVTree;
   
    // The handle that this storage represents, updated when data is registered to ZoneGraphSubsystem, used for query results.
    FZoneGraphDataHandle DataHandle;
};

USTRUCT()
struct ZONEGRAPH_API FZoneData  // 对应一个AZoneShape,代表一段路,里面包含多条Lane。
{
    GENERATED_BODY()
    int32 GetLaneCount() const { return LanesEnd - LanesBegin; }
    // Zone边界线的第一个点在FZoneGraphStorage::BoundaryPoints中的下标。
    UPROPERTY()
    int32 BoundaryPointsBegin = 0;
    // Zone边界线最后一个点的下标.
    UPROPERTY()
    int32 BoundaryPointsEnd = 0;
    // Zone第一条Lane在FZoneGraphStorage::Lanes中的下标
    UPROPERTY()
    int32 LanesBegin = 0;
    // Zone最后一条Lane的下标
    UPROPERTY()
    int32 LanesEnd = 0;
    // Zone的Bounding box
    UPROPERTY()
    FBox Bounds = FBox(ForceInit);
    // Zone tags
    UPROPERTY()
    FZoneGraphTagMask Tags = FZoneGraphTagMask(1);  // Default Tag
};

Lane

路网上的一条路线,由路点组成,有方向,有宽度。Lane之间互相连接。

USTRUCT()
struct ZONEGRAPH_API FZoneLaneData
{
    GENERATED_BODY()
    int32 GetLinkCount() const { return LinksEnd - LinksBegin; }
    int32 GetNumPoints() const { return PointsEnd - PointsBegin; }
    int32 GetLastPoint() const { return PointsEnd - 1; }
   
    //  lane的宽度
    UPROPERTY()
    float Width = 0.0f;
    // Lane上的标签
    UPROPERTY()
    FZoneGraphTagMask Tags = FZoneGraphTagMask(1);  // Default Tag
    // Lane的第一个点在FZoneGraphStorage::LanePoints中的下标
    UPROPERTY()
    int32 PointsBegin = 0;
    // Lane最后一个点的下标
    UPROPERTY()
    int32 PointsEnd = 0;
    // 当前Lane的第一条连接的索引
    UPROPERTY()
    int32 LinksBegin = 0;
    // 当前Lane的最后一条连接的索引
    UPROPERTY()
    int32 LinksEnd = 0;
    // Lane所属的Zone
    UPROPERTY()
    int32 ZoneIndex = 0;
    // Source data entry ID, this generally corresponds to input data point index.
    UPROPERTY()
    uint16 StartEntryId = 0;
    // Source data entry ID.
    UPROPERTY()
    uint16 EndEntryId = 0; 
};

// 描述两条Lane之间的空间关系
UENUM()
enum class EZoneLaneLinkType : uint8
{
    None                = 0,
    All                 = MAX_uint8,
    Outgoing            = 1 << 0,   // 离开当前Lane,通往另一条Lane
    Incoming            = 1 << 1,   // 从另一条Lane进入当前Lane
    Adjacent            = 1 << 2,   // 两条Lane归属于同一个Zone,紧邻当前Lane, 两条Lane的方向可能相同也可能不同。
};
ENUM_CLASS_FLAGS(EZoneLaneLinkType)
// 描述紧邻的两条Lane之间更多空间细节(只用在紧邻的两条Lane之间)
UENUM()
enum class EZoneLaneLinkFlags : uint8
{
    None                = 0,
    All                 = MAX_uint8,
    Left                = 1 << 0,   // 在当前Lane的左侧
    Right               = 1 << 1,   // 在Lane的右侧
    Splitting           = 1 << 2,   // 分叉,两条Lane的起点相同
    Merging             = 1 << 3,   // 两条Lane归并到一条Lane,两条Lane的终点相同
    OppositeDirection   = 1 << 4,   // 两条Lane方向相反
};
ENUM_CLASS_FLAGS(EZoneLaneLinkFlags)

USTRUCT()
struct ZONEGRAPH_API FZoneLaneLinkData // 描述当前Lane跟另一条Lane的连接信息
{
    GENERATED_BODY()
    FZoneLaneLinkData() = default;
    FZoneLaneLinkData(const int32 InDestLaneIndex, const EZoneLaneLinkType InType, const EZoneLaneLinkFlags InFlags) : DestLaneIndex(InDestLaneIndex), Type(InType), Flags((uint8)InFlags) {}
    bool HasFlags(const EZoneLaneLinkFlags InFlags) const { return (Flags & (uint8)InFlags) != 0; }
    EZoneLaneLinkFlags GetFlags() const { return (EZoneLaneLinkFlags)Flags; }
    void SetFlags(const EZoneLaneLinkFlags InFlags) { Flags = (uint8)InFlags; }
   
    /** 另一条Lane的索引*/
    UPROPERTY()
    int32 DestLaneIndex = 0;
    /** 连接的类型 */
    UPROPERTY()
    EZoneLaneLinkType Type = EZoneLaneLinkType::None;
    /** 当两条Lane毗邻时,更多信息 */
    UPROPERTY()
    uint8 Flags = 0;
};



交叉路口参数含义

项目配置中交叉路口各参数含义

MassTrafficSettings.h

/**
 * Settings for the MassTraffic plugin.
 */
UCLASS(config = Plugins, defaultconfig, DisplayName = "Mass Traffic", 
dontCollapseCategories)
class MASSTRAFFIC_API UMassTrafficSettings : public UMassModuleSettings
{
   
    /** ...........省略红绿灯无关配置 */

      /** 黄灯持续的时间 */
      UPROPERTY(EditAnywhere, Config, Category="Intersections|Durations|Standard")
      float StandardTrafficPrepareToStopSeconds = 2.0f;

      /** 人行通道开放需要的最少等待人数,个人建议配置成1  */
      UPROPERTY(EditAnywhere, Config, Category="Intersections|Pedestrians")
      int32 MinPedestriansForCrossingAtTrafficLights = 3;

      /** stop-sign intersections特殊人行通道开放需要的最少等待人数 */
      UPROPERTY(EditAnywhere, Config, Category="Intersections|Pedestrians")
      int32 MinPedestriansForCrossingAtStopSigns = 3;

      /** 普通交叉路口人行道开放的概率 */
      UPROPERTY(EditAnywhere, Config, Category="Intersections|Pedestrians")
      float TrafficLightPedestrianLaneOpenProbability = 1.0f; 

      /**  stop-sign intersections特殊人行通道开放概率  */
      UPROPERTY(EditAnywhere, Config, Category="Intersections|Pedestrians")
      float StopSignPedestrianLaneOpenProbability = 0.2f;
}

交叉路口Generator各参数含义

MassTrafficIntersectionSpawnDataGenerator.h

UCLASS()
class MASSTRAFFIC_API UMassTrafficIntersectionSpawnDataGenerator : 
public UMassEntitySpawnDataGeneratorBase
{
   
public:
      /** 每一条分叉路搜寻自己所对应的红绿灯的搜寻距离 */
      UPROPERTY(EditAnywhere, Category="Traffic Lights")
      float TrafficLightSearchDistance = 400.0f;

      /** 每一条分叉路搜寻自己所控制的人行道的最大搜寻距离 */
      UPROPERTY(EditAnywhere, Category="Pedestrians")
      float IntersectionSideToCrosswalkSearchDistance = 500.0f;

      /** 标准情况下机动车道绿灯持续的时间 */
      UPROPERTY(EditAnywhere, Category="Durations|Standard")
      float StandardTrafficGoSeconds = 20.0f;

      /** 标准情况下机动车道绿灯的最小持续时间,确保车子可以开进十字路口*/
      UPROPERTY(EditAnywhere, Category="Durations|Standard")
      float StandardMinimumTrafficGoSeconds = 5.0f;

      /** 标准情况下人行道绿灯持续时间 */
      UPROPERTY(EditAnywhere, Category="Durations|Standard")
      float StandardCrosswalkGoSeconds = 10.0f;

      /** 车道可以同时向前、向左、向右通行时绿灯持续时间 */
      UPROPERTY(EditAnywhere, Category="Durations|FourWay")
      float  UnidirectionalTrafficStraightRightLeftGoSeconds = StandardTrafficGoSeconds / 2.0f;

      /** 车道可以向前以及向右通行时绿灯持续时间 */
      UPROPERTY(EditAnywhere, Category="Durations|FourWay")
      float UnidirectionalTrafficStraightRightGoSeconds = StandardTrafficGoSeconds / 2.0f;

      /** 当前车道以及对向车道同时允许直行以及右转的绿灯时间 */
      UPROPERTY(EditAnywhere, Category=
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值