16. - Monster AI, Patrol, Trace

Overcle·2023년 2월 21일
0

학원

목록 보기
8/29

요약
1. 순찰 알고리즘이 직선이면 딱딱하니 스프라이닝? 작업을 해서 곡선 순찰을 돌도록 한다.
2.

오전 :
오후 :

용어 설명
1.

Tip
1.

따로 공부해서 정리해둘것
1.

Monster AI


[BTDecorator_CheckDistance.cpp]

	//몬스터의 위치와 타겟의 위치를 이용하여 거리를 구함.

	FVector MonsterLoc = Monster->GetActorLocation();
	FVector TargetLoc = Target->GetActorLocation();

	//FVector::Distance 는 두 인자의 거리를 구해준다.
	float Distance = FVector::Distance(MonsterLoc, TargetLoc);
	float Check = 0.f;

	switch (mCheckType)
	{
		case ECheckDistanceType::Attack:
			Check = Info.AttackDistance;
		break;

		case ECheckDistanceType::Trace:
			Check = Info.TraceDistance;
		break;
	}

	return Distance <= Check;

Monster Patrol


실체 구현은 테스크로 진행한다.

클래스 > Monstr > AI > 우클릭 > 모든 클래스 > BTTaskNode > "BTTask_TargetTrace" 생성

헤더파일 수정

MonsterTable 에서 몬스터 이동속도 400으로 설정. (플레이어와 몬스터 이동속도 차이 때문에)

Monster NavMesh


NavMesh 할 때 주의점은 모든 영역을 한번에 깔려고 하지말고 부분마다 할당하도록 하는걸 권장한다.


새 엑터 > 볼륨 > NavMeshBoundsVolume 엑터를 생성 한다
해당 액터 안에 있는 부분을 계산하는 방식이다.
"P"버튼을 누르면 구역을 확인할 수 있다.

NavMeshBoundsVolume 액터로 기반을 깔고.
NevAgent로 이동한다.

Pawn 부모클래스를 찾아가 보면 Actor 와 NevInterfase도 부모로 참조하고있다.

[BTTask_TargetTrace.h]

class UE11_API UBTTask_TargetTrace : public UBTTaskNode
{
	GENERATED_BODY()

public:
	UBTTask_TargetTrace();
	
protected:
	virtual void TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds);
	virtual void OnTaskFinished(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, EBTNodeResult::Type TaskResult);
	virtual EBTNodeResult::Type AbortTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory);
	virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory);

};
[BTTask_TargetTrace.cpp]


// Fill out your copyright notice in the Description page of Project Settings.


#include "BTTask_TargetTrace.h"
#include "../MonsterAIController.h"
#include "../Monster.h"
#include "../MonsterAnimInstance.h"

UBTTask_TargetTrace::UBTTask_TargetTrace()
{
	//노드 이름 지정
	NodeName = TEXT("TargetTrace");

	// TickTask 를 사용하기 위해서는 필수 True 변경
	bNotifyTick = true;

	// ?
	bCreateNodeInstance = true;
}

//테스크가 실행할 떄 한번 실행된다.
EBTNodeResult::Type UBTTask_TargetTrace::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
	// 부모 함수를 불러온다.
	EBTNodeResult::Type  result = Super::ExecuteTask(OwnerComp, NodeMemory);

	//해당 테스크를 실행 하고 있는 Owner의 Controller를 가져온다
	AMonsterAIController* Controller = Cast<AMonsterAIController>(OwnerComp.GetAIOwner());

	// Controller를 불러오지 못하면 Node 실패를 호출하고 종료한다.
	if (!IsValid(Controller))
		return EBTNodeResult::Failed;

	//Controller의 Pawn 정보를 불러온다.
	AMonster* Monster = Cast<AMonster>(Controller->GetPawn());

	//Pawn 정보를 불러오는데 실패하면 Node도 종료한다.
	if (!IsValid(Monster))
		return EBTNodeResult::Failed;


	//Pawn의 Animation 정보를 불러온다.
	UMonsterAnimInstance* Anim = Monster->GetMonsterAnimInst();

	//Target의 위치를 불러오기 위한 변수 선언. 타겟이 무엇인지 판별은 Detect 함수에 있다.
	AActor* Target = Cast<AActor>(Controller->GetBlackboardComponent()->GetValueAsObject(TEXT("Target")));

	//타겟정보를 불러오지 못했다면. (몬스터 근처에 플레이어가 접근을 안했을 시)
	if (!IsValid(Target))
	{
		//이동을 금지.
		Controller->StopMovement();

		// 애니메이션 Idle.
		Anim->ChangeAnim(EMonsterAnimType::Idle);


		//타겟 추적 실패 호출.
		return EBTNodeResult::Failed;
	}

	//타겟 위치로 이동시킨다  사용하기위에서는 빌드.cs에 네이게이션시스템을 추가해야한다.
	//길이 막혀 이동이 불가능한 상황이 발생하게 된다면 최대한 가까운데 까지 이동한다.
	UAIBlueprintHelperLibrary::SimpleMoveToActor(Controller, Target);


	//아래 방법도 존재하지만 반응하는게 차이가 있다. 이방법은 2번 호출된다. 실패와 성공. 장점은 도착 엑터 도착 반경까지 체크한다.
	//Controller->MoveToActor();


	//추적 애니메이션 호출.
	Anim->ChangeAnim(EMonsterAnimType::CombatRun);
	// 몬스터가 타겟에 도착 할 때 까지 해당 테스크를 빠져나가지 못하게한다.

	// 추적 노드가 실행중이다는 결과를 반환.
	return EBTNodeResult::InProgress	;

}


// Task가 중단될때 호출.
EBTNodeResult::Type UBTTask_TargetTrace::AbortTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
	EBTNodeResult::Type result = Super::AbortTask(OwnerComp, NodeMemory);


	return result;

}

// Task의 메인 함수이며  bNotifyTick 변수가 True일때만 작동한다.
void UBTTask_TargetTrace::TickTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, float DeltaSeconds)
{
	Super::TickTask(OwnerComp, NodeMemory, DeltaSeconds);

	//해당 Task 포함된 BehaviorTree를 들고있는 AICOntroller를  호출.
	AMonsterAIController* Controller =
		Cast<AMonsterAIController>(OwnerComp.GetAIOwner());

	//해당 Controller가 들고있는 Pawn정보를 호출.
	AMonster* Monster = Cast<AMonster>(Controller->GetPawn());


	//해당 Pawn의 Anim정보를 호출.
	UMonsterAnimInstance* Anim = Monster->GetMonsterAnimInst();

	//Controller 정보를 못받았다면.
	if (!IsValid(Controller))
	{
		//테스크를 강제로 종료
		FinishLatentTask(OwnerComp, EBTNodeResult::Failed);
		return;
	}

	// Target정보를 호출.
	ACharacter* Target = Cast<ACharacter>(Controller->GetBlackboardComponent()->GetValueAsObject(TEXT("Target")));


	// 아직 Detected를 하지못하여 타겟정보가 없을 시.
	if (!IsValid(Target))
	{
		//AI Controller에 움직임 정지 함수 호출.
		Controller->StopMovement();

		//Anim 정지 호출
		Anim->ChangeAnim(EMonsterAnimType::Idle);


		//추적 실패 호출
		FinishLatentTask(OwnerComp, EBTNodeResult::Failed);

		return ;
	}


	// 추후 공격 구현 할때 Monster의 AttackDistance를 구할 목적으로 선언
	const FMonsterInfo& Info = Monster->GetMonsterInfo();


	//Mosnter와 Target의 거리를 구함
	FVector MonsterLoc = Monster->GetActorLocation();
	FVector TargetLoc = Target->GetActorLocation();

	//각 인자의 위치 정보값에 각각 가지고있는 Capsule의 중간높이를 더해준다.
	MonsterLoc = MonsterLoc + FVector(0.f, 0.f, Monster->GetCapsuleComponent()->GetScaledCapsuleHalfHeight());
	TargetLoc = TargetLoc + FVector(0.f, 0.f, Target->GetCapsuleComponent()->GetScaledCapsuleHalfHeight());

	//두 인자의 거리 값을 구함
	float Distance = FVector::Distance(MonsterLoc, TargetLoc);

	//각각 가지고 있는 자신의 Capsule의 반경을 뺀다.
	//위에 Capsule의 중간위치, 그리고 반경을 뺀값의 거리를 저장한다.
	Distance -= Monster->GetCapsuleComponent()->GetScaledCapsuleRadius();
	Distance -= Target->GetCapsuleComponent()->GetScaledCapsuleRadius();


	//위의 수식을 계산한 값이. 공격 거리보다 작으면 멈춘다
	if (Distance <= Info.AttackDistance)
	{
		//움직임을 멈춤
		Controller->StopMovement();

		//지금은 Idle로 하지만 추후 공격부분을 구현하면 변경해야함.
		Anim->ChangeAnim(EMonsterAnimType::Idle);

		//목표물이 공격 범위까지 접근을 완료했음을 알림.
		FinishLatentTask(OwnerComp, EBTNodeResult::Succeeded);
	}
}


// 종료될때 실행된다.
void UBTTask_TargetTrace::OnTaskFinished(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory, EBTNodeResult::Type TaskResult)
{
	Super::OnTaskFinished(OwnerComp, NodeMemory, TaskResult);
}
[Monster.cpp]
		//이동속도 저장
		//앉아서 이동시 반으로 저장
		GetCharacterMovement()->MaxWalkSpeed = mInfo.MoveSpeed;
		GetCharacterMovement()->MaxWalkSpeedCrouched = mInfo.MoveSpeed /2;

빌드.cs 에 모듈을 추가한다
NavigationSystem

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

Monster Attack


클레스 > Monster > AI > 새클래스 > 모든 클래스 > BTTaskNode > _Attack 생성

헤더 수정

00
추후 추가 예정

Monster Partrol


추후 추가 예정

profile
게임 프로그래머 지망생의 발자취

0개의 댓글