UE4的NavArea,AreaFlags和Recast的dtPoly的关系

Posted haisong1991

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE4的NavArea,AreaFlags和Recast的dtPoly的关系相关的知识,希望对你有一定的参考价值。


UE的导航网格底层使用的是Recast Navigation,而Recast将网格划分为一个个凸多边形,平时寻路基本上都是使用这些多边形。

/// Defines a polyogn within a dtMeshTile object.
/// @ingroup detour
struct dtPoly

	/// Index to first link in linked list. (Or #DT_NULL_LINK if there is no link.)
	unsigned int firstLink;

	/// The indices of the polygon‘s vertices.
	/// The actual vertices are located in dtMeshTile::verts.
	unsigned short verts[DT_VERTS_PER_POLYGON];

	/// Packed data representing neighbor polygons references and flags for each edge.
	unsigned short neis[DT_VERTS_PER_POLYGON];

	/// The user defined polygon flags.
	unsigned short flags;

	/// The number of vertices in the polygon.
	unsigned char vertCount;

	/// The bit packed area id and polygon type.
	/// @note Use the structure‘s set and get methods to acess this value.
	unsigned char areaAndtype;

	/// Sets the user defined area id. [Limit: < #DT_MAX_AREAS]
	inline void setArea(unsigned char a)  areaAndtype = (areaAndtype & 0xc0) | (a & 0x3f); 

	/// Sets the polygon type. (See: #dtPolyTypes.)
	inline void setType(unsigned char t)  areaAndtype = (areaAndtype & 0x3f) | (t << 6); 

	/// Gets the user defined area id.
	inline unsigned char getArea() const  return areaAndtype & 0x3f; 

	/// Gets the polygon type. (See: #dtPolyTypes)
	inline unsigned char getType() const  return areaAndtype >> 6; 
;

仔细观察这个结构,发现能够自定义的地方有两个,一个是flags,16位,另外一个是areaAndtype,8位,而areaAndtype中使用6位表示area,2位表示type,area是可以用来存储自定义数据的。

在UE中,和导航区域类型有关的有UNavArea。NavArea表示一个区域,导航构建时把区域的类型写入到recast。另外NavArea中还有一个AreaFlags,也会同时写入,这个AreaFlas可以自己定义,默认为1,0表示不可行走。另外,NavigationQueryFilter可以使用这些标志来进行查询,设置在查询时候使用哪些类型或者排除哪些类型。

// 
// Use UNavigationSystem.DescribeFilterFlags() to setup user friendly names of flags
// 
USTRUCT()
struct NAVIGATIONSYSTEM_API FNavigationFilterFlags

	GENERATED_USTRUCT_BODY()

#if CPP
	union
	
		struct
		
#endif
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag0 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag1 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag2 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag3 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag4 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag5 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag6 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag7 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag8 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag9 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag10 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag11 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag12 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag13 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag14 : 1;
	UPROPERTY(EditAnywhere, Category=Flags)
	uint32 bNavFlag15 : 1;
#if CPP
		;
		uint16 Packed;
	;
#endif
;

另外还有一个NavLink,用来连接不同的区域,使用flags的最高位来表示。

// setting up the last bit available in dtPoly::flags
NavLinkFlag = ARecastNavMesh::FNavPolyFlags(1 << (sizeof(((dtPoly*)0)->flags) * 8 - 1));

如果要查询当前的多边形的区域类型,通过查询多边形的area可以获得areaID,然后就可以获得id对应的UClass。遗憾的是,areaid和flag是和类一一对应的,存储在UClass的default object中,同一个NavArea类对应的多边形的area和flag都是一样的。比如说,在场景中,部署两个NavModifier,修改区域类型为Obstacle,那么在导航时,我可以通过查询多边形来得知当前我在Obstacle区域中,但是却无法得知在哪一个Obstacle区域。

所以如果有类似的需求,要么修改引擎代码,新增字段将额外的信息写入,或者想办法复用16位的flag,或者将额外的信息存储在别处。前两种方法需要改引擎,后一种方法看起来更方便些,比如说可以在导航构建后将不同区域的多边形保存,然后在需要的时候进行查询。

以上是关于UE4的NavArea,AreaFlags和Recast的dtPoly的关系的主要内容,如果未能解决你的问题,请参考以下文章

ue4和ue5区别

ue4 c++代码怎么获取场景中的一个actor

努比亚z17有没有第三方rec的

ue4和渲染谁赚钱

MXNet im2rec.py使用教程

MXNet im2rec.py使用教程