[Unreal] 10.AI

본 문서는 어소트락 언리얼엔진 게임프로그래머 양성과정의 강의를 토대로 필기한 내용입니다

AI

컴포넌트

  • AIPerception(AI 인지 컴포넌트)
    • 각종 감지 환경 설정 가능
  • AIPerceptionStimuliSource(AI 감지 자극 소스)
    • Pawn 종류들은 기본으로 자극소스로 자동 등록이 됨
    • 만약 이걸 꺼주려면 DefaultGame.ini 파일에 [/script/AIModule.AISense_Sight]bAutoRegisterAllPawnsAsSources=false 를 추가하면 꺼준다

구조

  • AIController가 AIPawn에 빙의하여 동작하는 구조
    • 위 두가지 Perception 컴포넌트는 AIController가 가진다
    • AI 자동빙의 (Disable/Placed In World/Spawned/Placed In World or Spawned)
    • AI 컨트롤러 클래스를 상속받는 DefaultAIController를 커스텀해서 사용
  • AIPawn 뼈대로 만들고 AIMonster(MonsterPawn)를 파생클래스로 만들어서 사용한다
    • AIPawn에 캡슐 컴포넌트, 스켈레탈메쉬, 플로팅폰 무브먼트, 비헤이비어 트리, 죽음 델리게이트, HUD, MaterialInstaceDynamic 등을 멤버변수로 만들고 사용

이벤트

  • 충돌처리와 같이 델리게이트로 만들어서 사용할 수 있다
  • 감지 델리게이트

  • IGenericTeamAgentInterface 인터페이스 클래스를 상속받아서 virtual 함수를 재정의 하여서 팀 분류

인공지능

블랙보드

AI의 기억 공간, BT가 결정을 하기 위해 사용할 Key값이 저장되는 곳

  • 타입
    • 오브젝트
      • 타겟 : AI가 적(플레이어)을 기억하기 위해 오브젝트 타입으로 키 저장
    • 불린
      • AttackEnd : 공격 끝나는 시점에 비헤이비어 트리의 분기를 결정하기 위해 저장
    • 플롯
      • AttackDistance : 공격 거리를 벗어났을 때, 트리의 분기를 결정하기 위해 저장

비헤이비어 트리

블랙보드의 키에 기억된 정보를 이용해서 행동을 실행하는 곳

  • 특징
    • 루트의 Child의 단 하나만 존재
    • Child의 Child는 여러 개 존재 가능
  • 컴포짓
    • 분기 노드가 실행되는 방식을 정의하는 노드
    • 셀렉터(Selector), 시퀀스(Sequence), 심플 패러렐(Simple Parallel)로 구성됨
      • 셀렉터 : 왼쪽에서 오른쪽으로 차례대로 실행, 하나의 자손 노드가 성공하면 다른 자손 노드는 실행되지 않음
      • 시퀀스 : 왼쪽에서 오른쪽으로 차례대로 실행, 모든 자손 노드가 성공해야 시퀀스는 성공, 자손 노드중 하나라도 실행에 실패하면 실행이 중단되고 시퀀스는 실패로 처리
      • 심플 패러렐 : 태스크 노드를 하나 지정해서 메인 태스크로 잡음. 메인 테스크와 아래 트리들이 동시에 실행됨. 메인 태스크의 실행이 끝나면 하위 트리들의 실행을 멈출지(Immediate), 하위 트리들의 실행이 끝날 때까지 기다릴지(Delayed)를 지정할 수 있음
  • 태스크
    • AI의 행동, 블랙보드 값의 변경 등 여러 작업이 실행되는 노드
  • 데코레이터
    • 특정 노드에 추가해서 일종의 조건문 역할을 함
    • 예) 블랙 보드의 타겟이 설정되었는지 아닌지를 확인할 때
    • 플로우 컨트롤
      • 관찰자 노티파이 : 언제 관찰자가 요청 중단을 할 지
  • 서비스
    • 특정 노드에 추가해서 주로 블랙보드의 내용을 확인하거나 업데이트에 사용하는 노드

네비게이션

  • NavMeshBoundsVolume 컴포넌트 추가
    • 브러시 셋팅을 통해 범위 조정 가능

Task

  • ExecuteTask : Task 실행시키는 함수
    • NodeResult 변수 리턴값으로 받음 (열거형 : Succeeded, Failed, Aborted, InProgress)
  • AbortTask : Task 중지
  • TickTask : 매 프레임마다 들어오는 함수, 내부에서 알아서 동작
  • OnTaskFinished : 태스크 종료될 때 호출되는 함수

  • Move_To Task Node
    • MoveReq 변수 : 노드 파라미터
      • 허용가능 반경 : 두 액터사이의 거리
      • 도달 테스트에 에이전트/목표 반경 포함 : 보스몬스터와 일반몬스터의 크기 차이 등을 고려
    • PerformMoveTask : 타겟 이동 명령을 내리는 함수
  • BTTask_TraceTarget 으로 C++ 생성 후 코드로 제어 가능

BTTask_TraceTarget.h

#include "../GameInfo.h"
#include "BehaviorTree/Tasks/BTTask_MoveTo.h"
#include "BTTask_TraceTarget.generated.h"

UCLASS()
class STUDY_240601_API UBTTask_TraceTarget : public UBTTask_MoveTo
{
	GENERATED_BODY()
	
public:
	UBTTask_TraceTarget();
	virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
	virtual void OnTaskFinished(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, EBTNodeResult::Type TaskResult) override;
};

BTTask_TraceTarget.cpp

#include "BTTask_TraceTarget.h"
#include "Tasks/AITask_MoveTo.h"
#include "DefaultAIController.h"
#include "AIPawn.h"

UBTTask_TraceTarget::UBTTask_TraceTarget()
{
	bNotifyTaskFinished = true; // Task 끝날때, 호출된다
}

EBTNodeResult::Type UBTTask_TraceTarget::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
	EBTNodeResult::Type Result = Super::ExecuteTask(OwnerComp, NodeMemory);

	FBTMoveToTaskMemory* MyMemory = CastInstanceNodeMemory<FBTMoveToTaskMemory>(NodeMemory);

	UAITask_MoveTo* MoveTask = MyMemory->Task.Get();

	// AI컨트롤러를 찾아옴
	AAIPawn* ControlPawn = OwnerComp.GetAIOwner()->GetPawn<AAIPawn>();
	if (IsValid(ControlPawn))
	{
		ControlPawn->ChangeAI(EAIType::Trace);
	}

	GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("Trace Start"));

	return Result;
}

void UBTTask_TraceTarget::OnTaskFinished(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, EBTNodeResult::Type TaskResult)
{
	Super::OnTaskFinished(OwnerComp, NodeMemory, TaskResult);

	switch (TaskResult)
	{
	case EBTNodeResult::Succeeded:
		GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("Trace Succeeded"));
		break;
	case EBTNodeResult::InProgress:
		GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("Trace InProgress"));
		break;
	case EBTNodeResult::Failed:
		GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("Trace Failed"));
		break;
	case EBTNodeResult::Aborted:
		GEngine->AddOnScreenDebugMessage(-1, 10.f, FColor::Red, TEXT("Trace Aborted"));
		break;
	}
}

AI 애니메이션

  • DataTable로 몬스터 DT 생성
    • 5가지 (Idle, Walk, Run, Attack, Die) 상태 만들기
    • 각 애니메이션 지정
    • 코드로 MonsterDefaultAnimTemplate을 만들고 생성자에서 DT CDO 생성한 후 초기화
    • SetAnimData() 함수를 통해 각 애니메이션 데이터 템플릿 값에 넣기
  • ABPT로 Monster Animation Blueprint Template 생성
    • mMap으로 SectionName 찾아서 지정해 주기
    • Hit의 경우 Additive로 처리
  • ABPT를 상속받은 ABP 생성
    • 각 몬스터별로 Animation BluePrint 가지고 해당 몬스터가 AnimationClass 가지게 생성자에서 초기화

과제

  • BP TaskNode를 만들어서 공격 모션이 나오게 만들어보기
  • 차주 Patrol 구현
  • UI 인트로

AIPawn 멤버변수 및 함수 정의부터 다시 시작


© 2023 Jinsoo Lee. All rights reserved.

Powered by Hydejack v9.1.6