언리얼 엔진 활용하기 - 11. AI 추가
이번 글에서는 AI를 추가해보려 한다.
뭐 대단한 AI를 넣는건 아니고,
그냥 특정 범위 내에 플레이어 접근하면 따라와서 공격하는 정도?
그리고 플레이어 죽으면 인식하지 않는 정도만 넣어볼거다.
일단 여기까지 하면
게임에 기본적인 부분은 다 다룰수 있을거라고 생각하고,
이제 부터는 아이디어와 기획의 싸움이라고 생각한다.
AI 부분이 끝난 뒤에는 나도 내 나름대로 이것 저것 추가해서
포트폴리오 제출용 완성작?을 하나 간단하게 만들어두려 한다.
그럼 시작해보자.
일단 AIControl을 상속받는 클래스 생성.
그리고 나서 MyCharacter.cpp에 아래 소스 추가.
#include "MyAIController.h"
// Sets default values
AMyCharacter::AMyCharacter()
{
...
AIControllerClass = AMyAIController::StaticClass(); // AI Controller, 따로 셋팅해주지 않으면 전부 같은 동작을 하게끔 되어 있다.
AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned; // 새롭게 생성되는 MyCharacter 마다 AMyIController 액터가 생성되며, 플레이어가 조종하는 캐릭터를 제외한 모든 캐릭터는 MYAIController 의 지배
}
그리고 캐릭터 블루프린트로 이동하여, 아래의 값을 MyAIController로 바꿔주자.
이제 AIController로 돌아와서 작업해주자.
먼저 추가할건 타이머를 추가하고, 일정 주기로 몬스터가 특정 반경내를 이동하게끔 추가해볼거다.
MyAIController.h에 아래 소스 추가.
public:
AMyAIController();
virtual void OnPossess(APawn* InPawn) override;
virtual void OnUnPossess() override;
static const FName HomePosKey; // 이건 나중에 쓸건데 일단 미리 만들어 둔다.
static const FName PatrolPosKey; // 이건 나중에 쓸건데 일단 미리 만들어 둔다.
static const FName TargetKey; // 이건 나중에 쓸건데 일단 미리 만들어 둔다.
private:
void OnTimer();
FTimerHandle AITimerHandle;
float TimerInterval;
그리고 MyAIController.cpp에 아래 소스 추가.
#include "NavigationSystem.h"
#include "Blueprint/AIBlueprintHelperLibrary.h"
const FName AMyAIController::HomePosKey(TEXT("HomePos"));
const FName AMyAIController::PatrolPosKey(TEXT("PatrolPos"));
const FName AMyAIController::TargetKey(TEXT("Target"));
AMyAIController::AMyAIController()
{
TimerInterval = 3.0f;
}
void AMyAIController::OnTimer()
{
UE_LOG(LogTemp, Warning, TEXT("AMyAIController::OnTimer"));
APawn* CurrentPawn = GetPawn();
if (CurrentPawn)
{
UNavigationSystemV1* NavSystem = UNavigationSystemV1::GetNavigationSystem(GetWorld());
if (nullptr == NavSystem)
{
UE_LOG(LogTemp, Warning, TEXT("NavSystem is nullptr!"));
return;
}
FNavLocation NextLocation;
if (NavSystem->GetRandomPointInNavigableRadius(FVector::ZeroVector, 500.0f, NextLocation)) // 500.f 반경에 아무 값이나 리턴해줌, 다만 네비 메쉬가 있어야함.
{
//UNavigationSystemV1::SimpleMoveToLocation(this, NextLocation.Location); // 이건 안되네,..?
UAIBlueprintHelperLibrary::SimpleMoveToLocation(this, NextLocation.Location); // 리턴해준 값으로 이동.
UE_LOG(LogTemp, Warning, TEXT("Next Location : %s"), *NextLocation.Location.ToString());
}
}
}
void AMyAIController::OnPossess(APawn* InPawn)
{
Super::OnPossess(InPawn);
GetWorld()->GetTimerManager().SetTimer(AITimerHandle, this, &AMyAIController::OnTimer, TimerInterval, true); // Timer
}
void AMyAIController::OnUnPossess()
{
Super::OnUnPossess();
GetWorld()->GetTimerManager().ClearTimer(AITimerHandle);
}
위 소스에 대한 설명은 주석으로 처리해놨다. 저정도만 알면 될 것 같고 나머지는 어떻게 응용하느냐의 차이일거다.
여기까지의 추가하고 실행하면, 빌드에러가 날건데 이 부분은 예전에 한번 UI추가할때 얘기한 부분인데,
위의 사진처럼 추가를 해줘야한다.
그리고 나서 다시 실행해보면 아마 변한게 없을거다. 그 이유는 네비게이션 메쉬를 추가해주지 않았기 때문이다.
위에 소스에서도 나오지만, 네비게이션 메쉬라는걸 추가하여, 그 범위를 설정해줘야지만 위의 소스는 정상동작한다.
위의 사진처럼 네비게이션 메쉬를 추가해주고, 크기를 설정해주자.
그리고 나서 실행하면 아마 캐릭터가 왔다갔다 하고 있을거다.
(나는 어짜피 다시 주석처리하고 막을 예정이기 때문에 실제 플레이를 하진 않아서 영상은 없다.)
여기까지는 단순히 예시를 보여주기 위한 작업이었고,
이제 본격적으로 블랙보드와 비헤이비어 트리를 이용하여,
AI를 만들어보려 한다.
글이 길어질거 같아서 다음 글에서 정리하겠다.