[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_ToTask NodeMoveReq변수 : 노드 파라미터- 허용가능 반경 : 두 액터사이의 거리
- 도달 테스트에 에이전트/목표 반경 포함 : 보스몬스터와 일반몬스터의 크기 차이 등을 고려
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 멤버변수 및 함수 정의부터 다시 시작