Why does clicking outside of NavMesh bounds in a click-to-move project make the player pawn attempt to move towards world origin?

I’ve created a maze using the top down template as the basis. I’m having problems getting player pawn movement to work correctly when clicking outside of the NavMesh bounds.

What works well The pawn moves towards the hit location when I click within the NavMesh.

What doesn’t work: When I click outside of the NavMesh, the player pawn attempts to move towards the world origin (0,0,0).

What should happen: The pawn should not move towards the world origin. What I want is for the pawn to move as close as possible to the mouse hit location while staying inside of the NavMesh bounds.

Naive solution

My first idea was to make a large plane mesh, create a new trace channel, and force all of the Get Hit Result By Cursor Under Channel nodes to use this new mesh and trace channel for pawn movement. To ensure that the pawn stayed within the bounds of the maze corridors, I wrapped all of my maze meshes with 1 meter tall collision meshes.

This solution solves the original problem of getting (0,0,0) when clicking outside of the NavMesh. However, this solution breaks when I start adding ramps that go below the Z-value of this large 2d plane mesh (see screenshot for examples of these ramps).

Now you might say that I should just lower the Z-value of the large 2d plane. This solves the issue of the ignored ramps, but it introduces a new issue. Since the camera is set at an angle, clicking outside of the maze meshes now sends the player pawn in a slightly different direction than the mouse hit, due to the Z-value difference between the newly-lowered 2d plane and the corridor pieces. This is incredibly disorienting for the player.

Solution ideas

I’m not sure what the solution would involve.

  • It would be great to not rely on a large 2d mesh for click detection, since generating a (mostly wasteful) NavMesh over the entire 16,000uu x 16,000uu space takes a toll on performance. However, I don’t know another way of getting click detection to get a result other than (0,0,0) in the absence of meshes.
  • Perhaps I should replace the Move To Hit Location node with a custom function that sets the player pawn’s velocity and direction towards the hit location?
  • It seems like obtaining an XY plane generated from the player pawn’s current Z-value could be useful.

Any help appreciated.

Idk how I got here (must have clicked related questions or somthing) but this seemed like a interesting problem that I could input some ideas.

I was thinking you could make a brush below everything that isn’t visible(Doesn’t need navmesh) that will catch any clicks and if the getmouseworld node’s z equals that brushes z value then it will get the current z value of the actor and use it with the xy from the getmouseworld to create a vector to pass to the simple move to node.

I dont know if the simple move to node would translate that to moving to the edge but you could create a bool variable in the regular move to location and set use pathfinding to false if the z value was from the brush below. You could then add some brushes for the pawn to collide with at the edges.

I’m not sure how it could work when looking through the camera at an angle though so you may have to change it around possibly but it could work.

Hey Nylira,

Are you basing this off of the Top Down Template? The default MyController Blueprint doesn’t run into this issue, because when you click somewhere the character can’t go the input is ignored. If you made some adjustments or made a brand new MyController, could you post a screenshot of your Blueprint so we can take a look?

Ben Halliday

Hi Ben,

I am basing it off of the Top Down Template. Here’s my customized version of the default “MyController”: http://i.imgur.com/1Z5OWjP.png

After your comment, I made a new project based off of the Top Down Template and copied the default “MyCharacter” and “MyController” blueprints into my current project. Using the default character/controller blueprints still seems to send the character to 0,0,0 when I click into the void.

Thanks for your suggestion. I tried out the first bit (a plane below everything set at -2000 units Z):

Unfortunately though I couldn’t get “Simple Move to Location” to do anything. I logged the hit value and the equality to -2000 succeeded, but the player pawn didn’t move. I suspect it’s because the plane isn’t part of the NavMesh.

I’ve been looking through the Blueprint nodes and I can’t seem to find one that will pause pathfinding.

You could try adding branches checking by the bool return values from the function.
These modules encapsulates the method LineTraceSingle( ) that just returns true if hits something.

This could solve the problem or at least minimize the “undesired” behaviour.

I guess the pro way to do this should be create a Blueprint function that breaks the HitResult and gets the PhisicalMaterial you hit, comparing it to some Material that you should just apply on the “walkable” surfaces, if they’re equal returns true to you use on a branch like shown on my suggestion.

I apologize by lack the skills to make a Blueprint graph from the function you really need. :frowning:

So when you copied the MyController blueprint over, you didn’t add the Right Click functions from your custom pzController? That makes me think the problem is in your level somehow. Just to eliminate the possibility that it’s your Blueprints, try bringing them over to your new Top Down project and make sure it isn’t happening in there.

Could you show me a Top Down screenshot of your map and indicate where you are clicking that is trying to send the character to 0,0,0? Move to Hit Location should not be activating if the location is not reachable. You mention you have multiple z values for your platforms. Try setting up Break Hit Result and Print String nodes to see what exactly is being returned when you click:

I’m clicking in the black area and here is the hit result: http://i.imgur.com/eJmznTE.png It sends the player pawn to 0,0,0.

I added a large plane at Z: -2000 (outside of the NavMesh): http://i.imgur.com/Q4ZHjZg.jpg And clicking on this one seems to not cause the character to move. However, I actually want the character to move. Not to 0,0,0, but to the edge of my platform in the direction of the click.

I stuck the large plane inside of the NavMesh at Z: -1000

It makes NavMesh generation much slower, but the result when clicking on the plane is closer what I’m looking to achieve. The player pawn attempts to reach the hit result on the plane, but can never reach it so it just tries to get as close as possible.

Below is a graphic of what I’m trying to achieve. When an out-of-bounds location is clicked, I want the player to move towards the hit result on the same Z-plane, not on the Z-plane of the clicked location:

Hey Nylira,

I’m still trying to get an answer for you on this, and apologize for the delay. I’m not able to reproduce what you’re seeing, so can you check and see if this same issue occurs in a new project? Thanks!

So, i had similar problems, since i am doing a Click&Move Game, and whenever i clicked outside of the navmesh, nothing happened. Though i wanted in that case, that the player just moves in the direction of the click. I solved this by doing some of the navigation queries “manually”, here is a solution if you already used c++ in your game:

First, instead of getting the HitResultUnderMouse you could create a virtual plane on every click, so you can project the coordinates always at the same height as the player is. Evengard did the Maths for it already, so it should be quite easy to incorporate into your code (https://answers.unrealengine.com/questions/20858/set-collision-settings-for-brushes.html) :slight_smile:

Afterwards we need to do something to the PlayerController. First, in the .h of your playercontroller, add 2 components:

/** Component used for pathfinding and querying environment's navigation. */
TSubobjectPtr<class UNavigationComponent> NavComponent;

/** Component used for moving along a path. */
TSubobjectPtr<class UPathFollowingComponent> PathFollowingComponent;

Then we need to initialize them on instantiation of the controller, so in your constructor-method you need to call them.

	// set up navigation component
	NavComponent = PCIP.CreateDefaultSubobject<UNavigationComponent>(this, TEXT("NavComponent"));

	PathFollowingComponent = PCIP.CreateDefaultSubobject<UPathFollowingComponent>(this, TEXT("PathFollowingComponent"));

Ok, so far so good. Now comes the fun part. I’ve bound the following method for LeftMouseClick:

void APlayGroundPlayerController::MoveToMouseCursor() {
	FVector dest;

	UNavigationComponent* PathFindingComp = FindComponentByClass<UNavigationComponent>();
	UPathFollowingComponent* PathFollowComp = FindComponentByClass<UPathFollowingComponent>();
	if (PathFindingComp != NULL && PathFollowComp != NULL) {
		bool bFoundPath = PathFindingComp->FindPathToLocation(dest, NULL);
		if (bFoundPath == false || PathFindingComp->GetPath().IsValid() == false) {
			bFoundPath = PathFindingComp->FindSimplePathToLocation(dest);
		if (bFoundPath == true && PathFindingComp->GetPath().IsValid() == true) {
			PathFollowComp->RequestMove(PathFindingComp->GetPath(), NULL, 100.0f);

(GetMouseClickCoords is my method where i pasted the code from Evengard) What are we doing in this method now:
First we try to find a path to the destination location through the navmesh (FindPathToLocation). If we couldnt find a path, or the path is not valid for whatever reason, we try to find a “path” without the navmesh, which means, the player just moves in the direction of the click. Then we request the actual move.

Hope this was understandable and helps any others in the future :slight_smile: