Unable to move a character from C++ with MoveToLocation()

I’ve been working on a turn based game in which characters can perform actions just like X-Com. I’ve been implementing my game in C++ for easier code maintanance, refactoring and debugging…

And for the task I have at hand I am restricted from using the AI system (Behaviour Trees) of the Unreal.

For character actions (like move to a destination, attack some target, use some skill etc.) I’ve implemented a generic action management system which is based on a custom base class called UAction.

Whenever a character takes an action, an instance of a class derived from UAction (Say UMoveAction) takes control of the character. This action instance has access to the character’s ai controller instance, the pawn/character class instance and also its animation instance. And it makes the character perform the action at hand respecting the action type (Move,Attack etc) for which the derived UAction is implemented for.

Now my problem is I am trying to make the character move using Unreal’s path planning. For this I’ve figured out there is the MoveToLocation(…) method inside the ai controller class of the character (derives from AAIController).

I have generated NavMesh which I can display with “P” button. And Navmesh works without a problem for other parts of my code.

My problem is no matter what I do my characters always fail to move. Once MoveToLocation() is called, it returns success but it seems it immediately fails in 1-2 frames following the tick it is called. The characters briefly starts playing the move animation but then they immediately stop.

Here is the section of the code in UMoveAction which is responsible for moving the character

EActionResult UMoveAction::OnPerform_Implementation(FActionCost & performCost)
{
	performCost.actionPointCost = 0.0f;
	performCost.movementCost = 0.0f;
	initialPathCost = 0.0f;
	currentPathCost = 0.0f;

	//Attempt to switch to able state if it fails return failure
	if (!animation->SetState()) {
		return EActionResult::FAILED;
	}

	//Unset any action montages that are set
	animation->SetAction();

	//Also unset upper body animation 
	//TODO: This may actually be set to an animation depending on characters current equipment
	//		i.e. a greatsword wielding character's upperbody will animate differently than a character with daggers when moving
	animation->SetUpperBodyAnim();

	
	EPathFollowingRequestResult::Type moveResult = ownerController->MoveToLocation(parameters.targetLocation);/*, acceptanceRadius, false, true, false, true);*/
	
	//If a path cannot be generated from the nav system return failure
	if (moveResult == EPathFollowingRequestResult::Failed) return EActionResult::FAILED;
	//Else if we are already at goal return success with zero cost
	else if (moveResult == EPathFollowingRequestResult::AlreadyAtGoal) return EActionResult::SUCCESSFUL;
	//Else we are now on the path return inconclusive with zero cost
	else {
		initialPathCost = ownerPathFollowingComponent->GetRemainingPathCost();
		return EActionResult::INCONCLUSIVE;
	}
}

owner is a reference to the character to which this action is applied to. ownerController is a reference to this character’s ai controller and ownerPathFollowingComponent is the UPathFollowingComponent reference which is set in character’s ai controller.

I’ve tried MoveToLocation(…) with many different parameter combinations (commented out in code) but it seems none of them make the character move (more then 1-2 frames).

What might be the problem in this case? Could you suggest where I should look at to solve this?

The funny thing is MoveToLocation always returns EPathFollowingRequestResult::Success for me.

Within an update routine I also check the status of the PathFollowingComponent and it is set to Moving as well.

However character does not move.

I’ve tried to create a basic test character with the Mannequin mesh in T-Pose. Within its blueprint’s Begin method I’ve called MoveToLocation from its controller and it works perfectly that way.

Plus I’ve also tried to debug with the VisualLogger. It accepts the path requests normally. It even shows a visual representation of the path within the editor and the paths seems correct.

But the character just waits there… And 3-4 seconds later another log message enters the Visual Logger screen saying that the path is blocked.

I dont know what blocks the path. I’ve checked every possible collidable object that may interfere with the character and all of them are set to no collision. I’ve also set the capsule and the skeletal mesh of the character so that they ignore their actor (character) on move.

Is it possible to see what kind of an object blocks a navigation path at runtime?

This is really driving me crazy… I’ve been working on it for over 3 days now with no success. I cant even manage to move a single character to a point 3 meters away from it from C++. The engine code is really poorly documented…

And I still cant figure out why this happens… Any help will be greatly appreciated.

I finally solved my problem.

I used to instantiate both the character controller and the character classes inside C++ code. I then call the possess function of the controllers to possess their corresponding characters within C++ again.

It appears the the character movement component needs additional initialization to set up correct. And instantiating the characters from the C++ side does not do that.

To do it I first set Auto Possess (or whatever its name was) to true in my character blueprint on editor side so that whenever the character is instantiated its corresponding controller is also instantiated, set up and auto-possesses the character. I also set the controller class to my own controller class in the editor.

Then I created the characters again from the C++ calling the SpawnAIFromClass(…) function. The class I pass in the function is my blueprint class.

This fixes the issue.

I hope the Epic team adds some detailed documentation for the C++ API. Not only the static documentation (which is missing a lot of details by itself as well) but perhaps a handful guide of “dos” and “do nots” or “how to dos” would be awesome for C++ coders.

1 Like

You are right. We need more details about the method or class in C++ documentation. Such as “how to use them”.

1 Like