4.7 - Project broken by lack of UNavigationComponent

On update my project, since looks like pathfinding changed, my custom NavigationSystem broke.

Looks like UNavigationComponent no longer is on the engine, as the method FindSimplePathToLocation( ) (this was my first heavy error on recompile after fix the “virtual voids” to some BlueprintEvent_Implementation( ) functions) I’m kind of lost now. Does someone knows the “replacement” to this method?

Thank you.

Another way to look at the same problem:

I have a custom NavigationSystem to perform specific movements, one of them relied on FindSimplePathToLocation( ) because:

  • This method just returns true when a direct straight path (point A - point B) was found.
  • It in some way filled an internal path (that I was retrieving using UNavigationComponent::GetPath( ) after) with just these two points, and so I could call a RequestMove( ) with this simple path as parameter.

So if I could test the direct path and in case of pass the test build a path with just these two points I’ll get the same effect, I’m watching the older NavigationComponent.cpp, but I think that I don’t need mock a custom method to replicate what it did*.

*Meaning, since the NavigationComponent was removed, how to get the same result/behaviour from FindSimplePathToLocation( ) on 4.7 “without” it?

ANSWER:

The “new?” pathfind system trough FPathFindingResult and FPathFindingQuery could be understood watching the UNavigationSystem::SimpleMoveToLocation( ) method.
By testing FPathFindingResult.Path.PathPoints.Num( ) == 2 (start and end) the system “theoretically” will point if it’s a straight line or not, so summing it to an IsSuccessful( ) test, the behaviour could be the same.

Dunno, if it’s the optimal solution, but at least got my game to work again. :smiley:

Thanks.

Two Options

1. Use the static accessible Navigation System



UNavigationSystem::FindPathToLocationSynchronously(...)


NavigationSystem.h



/** Finds path instantly, in a FindPath Synchronously. 
	 *	@param PathfindingContext could be one of following: NavigationData (like Navmesh actor), Pawn or Controller. This parameter determines parameters of specific pathfinding query */
	UFUNCTION(BlueprintCallable, Category = "AI|Navigation", meta = (HidePin = "WorldContext", DefaultToSelf = "WorldContext"))
	static UNavigationPath* FindPathToLocationSynchronously(UObject* WorldContext, const FVector& PathStart, const FVector& PathEnd, AActor* PathfindingContext = NULL, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL);

	/** Finds path instantly, in a FindPath Synchronously. Main advantage over FindPathToLocationSynchronously is that 
	 *	the resulting path with automatically get updated if goal actor moves more then TetherDistance away from last path node
	 *	@param PathfindingContext could be one of following: NavigationData (like Navmesh actor), Pawn or Controller. This parameter determines parameters of specific pathfinding query */
	UFUNCTION(BlueprintCallable, Category = "AI|Navigation", meta = (HidePin = "WorldContext", DefaultToSelf = "WorldContext"))
	static UNavigationPath* FindPathToActorSynchronously(UObject* WorldContext, const FVector& PathStart, AActor* GoalActor, float TetherDistance = 50.f, AActor* PathfindingContext = NULL, TSubclassOf<UNavigationQueryFilter> FilterClass = NULL);

//----------------------------------------------------------------------//
	// Public querying interface                                                                
	//----------------------------------------------------------------------//
	/** 
	 *	Synchronously looks for a path from @fLocation to @EndLocation for agent with properties @AgentProperties. NavData actor appropriate for specified 
	 *	FNavAgentProperties will be found automatically
	 *	@param ResultPath results are put here
	 *	@param NavData optional navigation data that will be used instead of the one that would be deducted from AgentProperties
	 *  @param Mode switch between normal and hierarchical path finding algorithms
	 */
	FPathFindingResult FindPathSync(const FNavAgentProperties& AgentProperties, FPathFindingQuery Query, EPathFindingMode::Type Mode = EPathFindingMode::Regular);

	/** 
	 *	Does a simple path finding from @StartLocation to @EndLocation on specified NavData. If none passed MainNavData will be used
	 *	Result gets placed in ResultPath
	 *	@param NavData optional navigation data that will be used instead main navigation data
	 *  @param Mode switch between normal and hierarchical path finding algorithms
	 */
	FPathFindingResult FindPathSync(FPathFindingQuery Query, EPathFindingMode::Type Mode = EPathFindingMode::Regular);

	/** 
	 *	Asynchronously looks for a path from @StartLocation to @EndLocation for agent with properties @AgentProperties. NavData actor appropriate for specified 
	 *	FNavAgentProperties will be found automatically
	 *	@param ResultDelegate delegate that will be called once query has been processed and finished. Will be called even if query fails - in such case see comments for delegate's params
	 *	@param NavData optional navigation data that will be used instead of the one that would be deducted from AgentProperties
	 *	@param PathToFill if points to an actual navigation path instance than this instance will be filled with resulting path. Otherwise a new instance will be created and 
	 *		used in call to ResultDelegate
	 *  @param Mode switch between normal and hierarchical path finding algorithms
	 *	@return request ID
	 */
	uint32 FindPathAsync(const FNavAgentProperties& AgentProperties, FPathFindingQuery Query, const FNavPathQueryDelegate& ResultDelegate, EPathFindingMode::Type Mode = EPathFindingMode::Regular);

	/** Removes query indicated by given ID from queue of path finding requests to process. */
	void AbortAsyncFindPathRequest(uint32 AsynPathQueryID);
	
	/** 
	 *	Synchronously check if path between two points exists
	 *  Does not return path object, but will run faster (especially in hierarchical mode)
	 *  @param Mode switch between normal and hierarchical path finding algorithms. @note Hierarchical mode ignores QueryFilter
	 *	@return true if path exists
	 */
	bool TestPathSync(FPathFindingQuery Query, EPathFindingMode::Type Mode = EPathFindingMode::Regular, int32* NumVisitedNodes = NULL) const;

	/** Finds random point in navigable space
	 *	@param ResultLocation Found point is put here
	 *	@param NavData If NavData == NULL then MainNavData is used.
	 *	@return true if any location found, false otherwise */
	bool GetRandomPoint(FNavLocation& ResultLocation, ANavigationData* NavData = NULL, TSharedPtr<const FNavigationQueryFilter> QueryFilter = NULL);

	/** Finds random point in navigable space restricted to Radius around Origin
	 *	@param ResultLocation Found point is put here
	 *	@param NavData If NavData == NULL then MainNavData is used.
	 *	@return true if any location found, false otherwise */
	bool GetRandomPointInRadius(const FVector& Origin, float Radius, FNavLocation& ResultLocation, ANavigationData* NavData = NULL, TSharedPtr<const FNavigationQueryFilter> QueryFilter = NULL) const;



2. Get the Nav data within your follow comp and use instanced versions



bool UYourFollowComp::GetRandomPointInRadius(const FVector& Origin, float Radius, FVector& OutResult)
{
	if (!MovementComp) 
	{
		return false;
	}
	//~~~~~~~~~~~~~~~~~~
	
	//Agent Properties
	const FNavAgentProperties& AgentProperties = MovementComp->GetNavAgentPropertiesRef();
	const ANavigationData * NavData = GetNavDataForProps(AgentProperties);
	if (!NavData) 
	{
		return false;
	}
	
	//Now here you can use Nav Data functions!
	
	NavData->YourDesiredFunction()
}


NavData.h



/** 
	 *	Synchronously looks for a path from @StartLocation to @EndLocation for agent with properties @AgentProperties. NavMesh actor appropriate for specified 
	 *	FNavAgentProperties will be found automatically
	 *	@param ResultPath results are put here
	 *	@return true if path has been found, false otherwise
	 *
	 *	@note don't make this function virtual! Look at implementation details and its comments for more info.
	 */
	FORCEINLINE FPathFindingResult FindPath(const FNavAgentProperties& AgentProperties, const FPathFindingQuery& Query) const
	{
		check(FindPathImplementation);
		// this awkward implementation avoids virtual call overhead - it's possible this function will be called a lot
		return (*FindPathImplementation)(AgentProperties, Query);
	}

	/** 
	 *	Synchronously looks for a path from @StartLocation to @EndLocation for agent with properties @AgentProperties. NavMesh actor appropriate for specified 
	 *	FNavAgentProperties will be found automatically
	 *	@param ResultPath results are put here
	 *	@return true if path has been found, false otherwise
	 *
	 *	@note don't make this function virtual! Look at implementation details and its comments for more info.
	 */
	FORCEINLINE FPathFindingResult FindHierarchicalPath(const FNavAgentProperties& AgentProperties, const FPathFindingQuery& Query) const
	{
		check(FindHierarchicalPathImplementation);
		// this awkward implementation avoids virtual call overhead - it's possible this function will be called a lot
		return (*FindHierarchicalPathImplementation)(AgentProperties, Query);
	}


Thanks Rama, I’ve implemented an additional method on my NavigationSystem that gets the result from FindPathSync( ) and counts the PathPoints as I told, got a bit confuse with this new Query and FPathFindingResult stuff, but I think that on this I’m OK.

Now got another trouble on another place! LOL