I created a NPC C++ class for a character that i want to walk around on the map animated, but
due to my beginner stage in unreal engine 4.27 i cannot figure out why it isn’t working properly.
Below is what i am noticing:
the animation is not playing properly, it plays and loops but the character is being reset to a previous position.
the angle the NPC is moving in is wrong.
the collision capsule (if that’s what it is) is located below the character and not covering the entire body.
The code i have for my NPC Character (if you need more code let me know):
// My NPC.cpp file
#include "NPC.h"
#include "NPCAIController.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
// Sets default values
ANPC::ANPC()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
// Find and set the skeletal mesh (replace the path with yours!)
static ConstructorHelpers::FObjectFinder<USkeletalMesh> MeshAsset(TEXT("SkeletalMesh'/Game/MeshyAI-Models/giant/Walking.Walking'"));
if (MeshAsset.Succeeded())
{
GetMesh()->SetSkeletalMesh(MeshAsset.Object);
GetMesh()->SetRelativeLocation(GetActorLocation()); // Adjust as needed for your model
GetMesh()->SetRelativeRotation(GetActorRotation());
}
// Find and set the walking animation (replace the path with yours!)
static ConstructorHelpers::FObjectFinder<UAnimationAsset> WalkAnim(TEXT("AnimSequence'/Game/MeshyAI-Models/giant/Walking_Anim.Walking_Anim'"));
if (WalkAnim.Succeeded())
{
GetMesh()->SetAnimationMode(EAnimationMode::AnimationSingleNode);
GetMesh()->PlayAnimation(WalkAnim.Object, true); // true = loop
}
// Tell Unreal to use our custom AI controller class (you'll create this in Step 3)
// In your Agiant constructor
AIControllerClass = ANPCAIController::StaticClass();
AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned;
// Set walk speed (must include CharacterMovementComponent header)
GetCharacterMovement()->MaxWalkSpeed = 150.0f; // Lower than default
}
// Called when the game starts or when spawned
void ANPC::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ANPC::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void ANPC::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
}
// My NPCAIController.cpp file
#include "NPCAIController.h"
#include "NavigationSystem.h"
#include "GameFramework/Character.h"
#include "Engine/World.h"
void ANPCAIController::BeginPlay()
{
Super::BeginPlay();
MoveToRandomLocation(); // Start moving once at spawn
}
void ANPCAIController::MoveToRandomLocation()
{
APawn* MyPawn = GetPawn();
if (!MyPawn) return;
UNavigationSystemV1* NavSys = UNavigationSystemV1::GetCurrent(GetWorld());
if (NavSys)
{
FVector Origin = MyPawn->GetActorLocation();
FNavLocation RandomLocation;
// Find a random point within 1000 units
if (NavSys->GetRandomReachablePointInRadius(Origin, 1000.0f, RandomLocation))
{
MoveToLocation(RandomLocation.Location);
}
}
}
void ANPCAIController::OnMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult& Result)
{
Super::OnMoveCompleted(RequestID, Result);
// Add a short delay before moving again (optional)
GetWorld()->GetTimerManager().SetTimerForNextTick([this]()
{
MoveToRandomLocation();
});
}