Using AIAsyncTaskBlueprintProxy (LNK2019)

This is an issue there’s quite a lot of answers about, but I’m not sure if this particular case is more unique, as I’ve tried all the usually listed answers and none seem to have worked.

Ultimately this issue is coming down to LNK2019 and 2001 errors about unresolved exernal symbols
For one reason or another I’m trying to create an AITaskProxy, very similar to MoveTo but with a provided rotation. In concept quite simple, but I’ve tried quite a few ways of implementing this to circumnavigate the issue, none have worked.

It seems as soon as AIAsynicTaskBlueprintProxy is used in any way, either through a variable, or through inheritance, I get this same issue. I’m not well versed in the minutae of how the Build.cs and dependencies REALLY work, so I’ve tried a rather scattergun approach that I’m not very proud of.

I’ve added “AIModule” to both public and private dependency module names, I’ve added “Runtime/AIMpdule/Classes” to PublicIncludePaths and “Runtime/AIModule/Private” to include PrivateIncludePaths, I’ve tried changing code I’ve made that inherits from blueprints in these sections to use the “AIMODULE_API” tag but whatever I do this doesn’t seem to work. Previously when I’ve done very similar things (making a K2 node that inherits from “UK2Node_BaseAsyncTask”) simply including “BlueprintGraph” in my public includes was enough. I don’t know if AIAsyncTaskBlueprintProxy is a unique case, because the header is a separate file, but the body is actually defined inside “AIBlueprintHelperLibrary” but I just can’t find a solution. Just to note, I have also been deleting intermediate and re-generating visual studio files frequently, as that’s been the cause of issues in the past.

Does anyone have any ideas? Has anyone ever tried to do the same?

Error Log:

3>     Creating library U:\Depot\MyGame\Intermediate\Build\Win64\UE4Editor\Development\UE4Editor-MyGame.lib and object U:\Depot\MyGame\Intermediate\Build\Win64\UE4Editor\Development\UE4Editor-MyGame.exp
3>TO_LatentFunctionLibrary.cpp.obj : error LNK2019: unresolved external symbol "public: void __cdecl UAIAsyncTaskBlueprintProxy::OnMoveCompleted(struct FAIRequestID,enum EPathFollowingResult::Type)" (?OnMoveCompleted@UAIAsyncTaskBlueprintProxy@@QEAAXUFAIRequestID@@W4Type@EPathFollowingResult@@@Z) referenced in function "private: static class UAIAsyncTaskBlueprintProxy * __cdecl UTO_LatentFunctionLibrary::CreateMoveToWithTurnProxy(class UObject *,class APawn *,struct FVector,class AActor *,struct FRotator,float,bool)" (?CreateMoveToWithTurnProxy@UTO_LatentFunctionLibrary@@CAPEAVUAIAsyncTaskBlueprintProxy@@PEAVUObject@@PEAVAPawn@@UFVector@@PEAVAActor@@UFRotator@@M_N@Z)
3>TO_LatentFunctionLibrary.cpp.obj : error LNK2019: unresolved external symbol "public: void __cdecl UAIAsyncTaskBlueprintProxy::OnNoPath(void)" (?OnNoPath@UAIAsyncTaskBlueprintProxy@@QEAAXXZ) referenced in function "private: static class UAIAsyncTaskBlueprintProxy * __cdecl UTO_LatentFunctionLibrary::CreateMoveToWithTurnProxy(class UObject *,class APawn *,struct FVector,class AActor *,struct FRotator,float,bool)" (?CreateMoveToWithTurnProxy@UTO_LatentFunctionLibrary@@CAPEAVUAIAsyncTaskBlueprintProxy@@PEAVUObject@@PEAVAPawn@@UFVector@@PEAVAActor@@UFRotator@@M_N@Z)
3>TO_LatentFunctionLibrary.cpp.obj : error LNK2019: unresolved external symbol "public: void __cdecl UAIAsyncTaskBlueprintProxy::OnAtGoal(void)" (?OnAtGoal@UAIAsyncTaskBlueprintProxy@@QEAAXXZ) referenced in function "private: static class UAIAsyncTaskBlueprintProxy * __cdecl UTO_LatentFunctionLibrary::CreateMoveToWithTurnProxy(class UObject *,class APawn *,struct FVector,class AActor *,struct FRotator,float,bool)" (?CreateMoveToWithTurnProxy@UTO_LatentFunctionLibrary@@CAPEAVUAIAsyncTaskBlueprintProxy@@PEAVUObject@@PEAVAPawn@@UFVector@@PEAVAActor@@UFRotator@@M_N@Z)
3>U:\Depot\MyGame\Binaries\Win64\UE4Editor-MyGame.dll : fatal error LNK1120: 3 unresolved externals

In my latest attempt at a solution, I’ve simply made a function as an alternative to the “UAIBlueprintHelperLibrary” function “CreateMoveToProxyObject” that performs the same process, but simply takes an additional input and calls my own version of “MoveTo” on the controller. Here’s the entire .cpp for that class:

#include "MyGame.h"
#include "TimerManager.h"
#include "Engine/Blueprint.h"
#include "Components/TO_AIController.h"
#include "Runtime/AIModule/Classes/Blueprint/AIBlueprintHelperLibrary.h"
#include "Runtime/AIModule/Classes/Blueprint/AIAsyncTaskBlueprintProxy.h"
#include "TO_LatentFunctionLibrary.h"




UAIAsyncTaskBlueprintProxy* UTO_LatentFunctionLibrary::CreateMoveToWithTurnProxy(UObject* WorldContextObject, APawn* Pawn, FVector Destination,
	AActor* TargetActor, FRotator TargetRotation, float AcceptanceRadius, bool bStopOnOverlap)
{
	if (Pawn == nullptr)
	{
		// maybe we can extract the pawn from the world context
		ATO_AIController* AsController = Cast<ATO_AIController>(WorldContextObject);
		if (AsController)
		{
			Pawn = AsController->GetPawn();
		}
	}

	if (!Pawn)
	{
		return NULL;
	}

	ATO_AIController* AIController = Cast<ATO_AIController>(Pawn->GetController());

	if (!AIController)
	{
		return NULL;
	}

	UAIAsyncTaskBlueprintProxy* MyObj = NULL;
	UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject);
	MyObj = NewObject<UAIAsyncTaskBlueprintProxy>(World);

	FAIMoveRequest MoveReq;
	MoveReq.SetUsePathfinding(true);
	MoveReq.SetAcceptanceRadius(AcceptanceRadius);
	MoveReq.SetReachTestIncludesAgentRadius(bStopOnOverlap);
	if (TargetActor)
	{
		MoveReq.SetGoalActor(TargetActor);
	}
	else
	{
		MoveReq.SetGoalLocation(Destination);
	}
	MoveReq.SetNavigationFilter(AIController->GetDefaultNavigationFilterClass());

	if (TargetActor && TargetRotation == FRotator::ZeroRotator)
	{
		TargetRotation = TargetActor->GetActorRotation();
	}

	FPathFollowingRequestResult ResultData = AIController->MoveToWithTurn(MoveReq, TargetRotation);
	switch (ResultData.Code)
	{
	case EPathFollowingRequestResult::RequestSuccessful:
		MyObj->AIController = AIController;
		MyObj->AIController->ReceiveMoveCompleted.AddDynamic(MyObj, &UAIAsyncTaskBlueprintProxy::OnMoveCompleted);
		MyObj->MoveRequestId = ResultData.MoveId;
		break;

	case EPathFollowingRequestResult::AlreadyAtGoal:
		World->GetTimerManager().SetTimer(MyObj->TimerHandle_OnInstantFinish, MyObj, &UAIAsyncTaskBlueprintProxy::OnAtGoal, 0.1f, false);
		break;

	case EPathFollowingRequestResult::Failed:
	default:
		World->GetTimerManager().SetTimer(MyObj->TimerHandle_OnInstantFinish, MyObj, &UAIAsyncTaskBlueprintProxy::OnNoPath, 0.1f, false);
		break;
	}
	
	return MyObj;
}

This post is a bit old, but for anybody who is having trouble with this:
In your game.build.cs file add the required modules in this line:

PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "NavigationSystem", "AIModule" });