AgentMaxSlope

AgentMaxSlope

#Overview

name: AgentMaxSlope

The value of this variable can be defined or overridden in .ini config files. 1 .ini config file referencing this setting variable.

It is referenced in 11 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of AgentMaxSlope is to define the maximum slope angle that an agent can traverse in the navigation mesh generated by Unreal Engine’s Recast navigation system. This setting is crucial for determining walkable areas in the game world and ensuring realistic movement for AI-controlled characters.

AgentMaxSlope is primarily used in the NavigationSystem module, specifically within the Recast navigation mesh generation process. It is a key parameter in the ARecastNavMesh class, which is responsible for creating and managing the navigation mesh.

The value of AgentMaxSlope is typically set in the constructor of FRecastNavMeshGenerationProperties or in the ARecastNavMesh class. It can be modified through the Unreal Engine editor or programmatically.

AgentMaxSlope interacts with other navigation-related variables such as AgentRadius, AgentHeight, and AgentMaxStepHeight. Together, these parameters define the physical characteristics of the agents that will use the navigation mesh.

Developers should be aware of the following when using AgentMaxSlope:

  1. It directly affects which areas are considered walkable in the game world.
  2. It has a significant impact on navigation mesh generation and performance.
  3. It must be balanced with other agent parameters for realistic movement.
  4. Changing this value may require regeneration of the navigation mesh.

Best practices when using AgentMaxSlope include:

  1. Set it to a realistic value based on the game’s requirements and the types of characters that will navigate the world.
  2. Consider the relationship between AgentMaxSlope and AgentMaxStepHeight to ensure consistent behavior.
  3. Test different values to find the optimal balance between realistic movement and performance.
  4. Be cautious when modifying this value, as it can have far-reaching effects on AI behavior and pathfinding.
  5. Use the clamp values (0.0 to 89.0 degrees) to prevent invalid inputs.

By carefully configuring AgentMaxSlope along with other navigation parameters, developers can create a more realistic and efficient navigation system for their game.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseEngine.ini:2826, section: [/Script/NavigationSystem.RecastNavMesh]

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Source/Runtime/NavigationSystem/Private/NavMesh/RecastNavMesh.cpp:430

Scope (from outer to inner):

file
function     FRecastNavMeshGenerationProperties::FRecastNavMeshGenerationProperties

Source code excerpt:

	AgentRadius = 34.f;
	AgentHeight = 144.f;
	AgentMaxSlope = 44.f;
	AgentMaxStepHeight = 35.f;
	MinRegionArea = 0.f;
	MergeRegionSize = 400.f;
	MaxSimplificationError = 1.3f;	// from RecastDemo
	TileNumberHardLimit = 1 << 20;
	RegionPartitioning = ERecastPartitioning::Watershed;

#Loc: <Workspace>/Engine/Source/Runtime/NavigationSystem/Private/NavMesh/RecastNavMesh.cpp:462

Scope (from outer to inner):

file
function     FRecastNavMeshGenerationProperties::FRecastNavMeshGenerationProperties

Source code excerpt:

	AgentRadius = RecastNavMesh.AgentRadius;
	AgentHeight = RecastNavMesh.AgentHeight;
	AgentMaxSlope = RecastNavMesh.AgentMaxSlope;
	AgentMaxStepHeight = RecastNavMesh.GetAgentMaxStepHeight(ENavigationDataResolution::Default); //FRecastNavMeshGenerationProperties is getting deprecated 
	MinRegionArea = RecastNavMesh.MinRegionArea;
	MergeRegionSize = RecastNavMesh.MergeRegionSize;
	MaxSimplificationError = RecastNavMesh.MaxSimplificationError;
	TileNumberHardLimit = RecastNavMesh.TileNumberHardLimit;
	RegionPartitioning = RecastNavMesh.RegionPartitioning;

#Loc: <Workspace>/Engine/Source/Runtime/NavigationSystem/Private/NavMesh/RecastNavMesh.cpp:822

Scope (from outer to inner):

file
function     void ARecastNavMesh::PostInitProperties

Source code excerpt:

		}

		if (AgentMaxSlope != DefOb->AgentMaxSlope)
		{
			UE_LOG(LogNavigation, Warning, TEXT("%s param: AgentMaxSlope(%f) differs from config settings, forcing value %f so it can be used with voxel cache!"),
				*GetNameSafe(this), AgentMaxSlope, DefOb->AgentMaxSlope);

			AgentMaxSlope = DefOb->AgentMaxSlope;
		}
	}
	
#if WITH_EDITORONLY_DATA
	bAllowWorldPartitionedNavMesh = UWorld::IsPartitionedWorld(GetWorld());
#endif // WITH_EDITORONLY_DATA

#Loc: <Workspace>/Engine/Source/Runtime/NavigationSystem/Private/NavMesh/RecastNavMesh.cpp:3443

Scope (from outer to inner):

file
function     void ARecastNavMesh::UpdateGenerationProperties

Source code excerpt:

	AgentRadius = GenerationProps.AgentRadius;
	AgentHeight = GenerationProps.AgentHeight;
	AgentMaxSlope = GenerationProps.AgentMaxSlope;

	AgentMaxStepHeight = GenerationProps.AgentMaxStepHeight;

	MinRegionArea = GenerationProps.MinRegionArea;
	MergeRegionSize = GenerationProps.MergeRegionSize;
	MaxSimplificationError = GenerationProps.MaxSimplificationError;

#Loc: <Workspace>/Engine/Source/Runtime/NavigationSystem/Private/NavMesh/RecastNavMeshGenerator.cpp:4681

Scope (from outer to inner):

file
function     void FRecastNavMeshGenerator::ConfigureBuildProperties

Source code excerpt:

	const float CellHeight = DestNavMesh->GetCellHeight(ENavigationDataResolution::Default);
	const float AgentHeight = DestNavMesh->AgentHeight;
	const float AgentMaxSlope = DestNavMesh->AgentMaxSlope;
	const float AgentMaxClimb = DestNavMesh->GetAgentMaxStepHeight(ENavigationDataResolution::Default);
	const float AgentRadius = DestNavMesh->AgentRadius;

	OutConfig.Reset();

	OutConfig.cs = CellSize;
	OutConfig.ch = CellHeight;
	OutConfig.walkableSlopeAngle = AgentMaxSlope;
	OutConfig.walkableHeight = FMath::CeilToInt(AgentHeight / CellHeight);
	OutConfig.walkableClimb = FMath::CeilToInt(AgentMaxClimb / CellHeight);
	OutConfig.walkableRadius = FMath::CeilToInt(AgentRadius / CellSize);
	OutConfig.maxStepFromWalkableSlope = OutConfig.cs * FMath::Tan(FMath::DegreesToRadians(OutConfig.walkableSlopeAngle));
	
	// For each navmesh resolutions, validate that AgentMaxStepHeight is high enough for the AgentMaxSlope angle
	for (int32 Index = 0; Index < (uint8)ENavigationDataResolution::MAX; Index++)
	{
		const ENavigationDataResolution Resolution = (ENavigationDataResolution)Index;
		
		const float MaxStepHeight = DestNavMesh->GetAgentMaxStepHeight(Resolution);
		const float TempCellHeight = DestNavMesh->GetCellHeight(Resolution);

#Loc: <Workspace>/Engine/Source/Runtime/NavigationSystem/Private/NavMesh/RecastNavMeshGenerator.cpp:4706

Scope (from outer to inner):

file
function     void FRecastNavMeshGenerator::ConfigureBuildProperties

Source code excerpt:

		// Compute the required climb to prevent direct neighbor filtering in rcFilterLedgeSpansImp (minh < -walkableClimb).
		// See comment: "The current span is close to a ledge if the drop to any neighbour span is less than the walkableClimb."
		const float RequiredClimb = DestNavMesh->GetCellSize(Resolution) * FMath::Tan(FMath::DegreesToRadians(AgentMaxSlope));
		const int RequiredClimbVx = FMath::CeilToInt(RequiredClimb / TempCellHeight);
		
		if (WalkableClimbVx < RequiredClimbVx)
		{
			// This is a log since we need to let the user decide which one of the parameters needs to be changed (if any).
			UE_LOG(LogNavigationDataBuild, Log, TEXT("%s: AgentMaxStepHeight (%f) for resolution %i is not high enough in steep slopes (AgentMaxSlope is %f). "

#Loc: <Workspace>/Engine/Source/Runtime/NavigationSystem/Private/NavMesh/RecastNavMeshGenerator.cpp:4716

Scope (from outer to inner):

file
function     void FRecastNavMeshGenerator::ConfigureBuildProperties

Source code excerpt:

				"This can also be avoided by using smaller CellSize and CellHeight."),
				*GetNameSafe(DestNavMesh), MaxStepHeight,
				*UEnum::GetDisplayValueAsText(Resolution).ToString(), AgentMaxSlope, (RequiredClimbVx-1)*TempCellHeight);	
		}
	}
	
	// store original sizes
	OutConfig.AgentHeight = AgentHeight;
	OutConfig.AgentMaxClimb = AgentMaxClimb;

#Loc: <Workspace>/Engine/Source/Runtime/NavigationSystem/Public/NavMesh/RecastNavMesh.h:80

Scope: file

Source code excerpt:

	Recast,							// Use walkableClimb value to filter
	None,							// Skip slope filtering
	UseStepHeightFromAgentMaxSlope	// Use maximum step height computed from AgentMaxSlope
};

struct FDetourTileSizeInfo
{
	unsigned short VertCount = 0;
	unsigned short PolyCount = 0;

#Loc: <Workspace>/Engine/Source/Runtime/NavigationSystem/Public/NavMesh/RecastNavMesh.h:358

Scope: file

Source code excerpt:

	/* The maximum slope (angle) that the agent can move on. */
	UPROPERTY(EditAnywhere, Category = Generation, meta = (ClampMin = "0.0", ClampMax = "89.0", UIMin = "0.0", UIMax = "89.0"))
	float AgentMaxSlope;

	/** Largest vertical step the agent can perform */
	UPROPERTY(EditAnywhere, Category = Generation, meta = (ClampMin = "0.0"))
	float AgentMaxStepHeight;

	/* The minimum dimension of area. Areas smaller than this will be discarded */

#Loc: <Workspace>/Engine/Source/Runtime/NavigationSystem/Public/NavMesh/RecastNavMesh.h:787

Scope (from outer to inner):

file
class        class ARecastNavMesh : public ANavigationData

Source code excerpt:

	/* The maximum slope (angle) that the agent can move on. */ 
	UPROPERTY(EditAnywhere, Category=Generation, config, meta=(ClampMin = "0.0", ClampMax = "89.0", UIMin = "0.0", UIMax = "89.0" ))
	float AgentMaxSlope;

	/** Largest vertical step the agent can perform */
	UE_DEPRECATED(5.3, "Set the AgentMaxStepHeight for the required navmesh resolutions in NavMeshResolutionParams.")
	UPROPERTY(config)
	float AgentMaxStepHeight;

#Loc: <Workspace>/Engine/Source/Runtime/NavigationSystem/Public/NavMesh/RecastNavMesh.h:803

Scope: file

Source code excerpt:


	/** Maximum vertical deviation between raw contour points to allowing merging (in voxel).
	 * Use a low value (2-5) depending on CellHeight, AgentMaxStepHeight and AgentMaxSlope, to allow more precise contours (also see SimplificationElevationRatio).
	 * Use very high value to deactivate (Recast behavior). */
	UPROPERTY(EditAnywhere, Category = Generation, config, meta = (ClampMin = "0"))
	int MaxVerticalMergeError;
	
	/** How much navigable shapes can get simplified - the higher the value the more freedom */
	UPROPERTY(EditAnywhere, Category = Generation, config, meta = (ClampMin = "0.0"))
	float MaxSimplificationError;