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

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

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

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

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

Naive solution

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

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

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

Solution ideas

I’m not sure what 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 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 absence of meshes.
  • Perhaps I should replace Move To Hit Location node with a custom function that sets player pawn’s velocity and direction towards hit location?
  • It seems like obtaining an XY plane generated from 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 getmouseworld node’s z equals that brushes z value then it will get current z value of actor and use it with xy from getmouseworld to create a vector to pass to simple move to node.

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

I’m not sure how it could work when looking through 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 Top Down Template? default MyController Blueprint doesn’t run into this issue, because when you click somewhere character can’t go 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?

Hi ,

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

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

Thanks for your suggestion. I tried out 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 hit value and equality to -2000 succeeded, but player pawn didn’t move. I suspect it’s because plane isn’t part of NavMesh.

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

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

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

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

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

So when you copied MyController blueprint over, you didn’t add Right Click functions from your custom pzController? That makes me think problem is in your level somehow. Just to eliminate 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 character to 0,0,0? Move to Hit Location should not be activating if 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 black area and here is hit result: http://i.imgur.com/eJmznTE.png It sends player pawn to 0,0,0.

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

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


It makes NavMesh generation much slower, but result when clicking on plane is closer what I’m looking to achieve. player pawn attempts to reach hit result on 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 player to move towards hit result on same Z-plane, not on Z-plane of clicked location:

Hey Nylira,

I’m still trying to get an answer for you on this, and apologize for 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 navmesh, nothing happened. Though i wanted in that case, that player just moves in direction of click. I solved this by doing some of navigation queries “manually”, here is a solution if you already used c++ in your game:

First, instead of getting HitResultUnderMouse you could create a virtual plane on every click, so you can project coordinates always at same height as player is. Evengard did 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 PlayerController. First, in .h of your playercontroller, add 2 components:

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

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

Then we need to initialize them on instantiation of 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 fun part. I’ve bound following method for LeftMouseClick:

void APlayGroundPlayerController::MoveToMouseCursor() {
	FVector dest;
	GetMouseClickCoords(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 code from Evengard) What are we doing in this method now:
First we try to find a path to destination location through navmesh (FindPathToLocation). If we couldnt find a path, or path is not valid for whatever reason, we try to find a “path” without navmesh, which means, player just moves in direction of click. Then we request actual move.

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

Cheers,