요약
1. 순찰 알고리즘이 직선이면 딱딱하니 스프라이닝? 작업을 해서 곡선 순찰을 돌도록 한다.
2.
오전 :
오후 :
용어 설명
1.
Tip
1.
따로 공부해서 정리해둘것
1.
[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;
실체 구현은 테스크로 진행한다.
클래스 > Monstr > AI > 우클릭 > 모든 클래스 > BTTaskNode > "BTTask_TargetTrace" 생성
헤더파일 수정
MonsterTable 에서 몬스터 이동속도 400으로 설정. (플레이어와 몬스터 이동속도 차이 때문에)
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 > AI > 새클래스 > 모든 클래스 > BTTaskNode > _Attack 생성
헤더 수정
00
추후 추가 예정
추후 추가 예정