전체적인 방향은 영상과 같다.
Monster-> AI -> BT,BB로 데이터 관리의 형태로 몬스터를 스폰할 예정이고
몬스터는 일반 몬스터, 정예 몬스터, 보스 몬스터로 존재할 것이고
보스 몬스터는 크기가 조금 클 예정이다.
#include "MonsterController.h"
#include "BehaviorTree/BlackboardData.h"
#include "BehaviorTree/BlackboardComponent.h"
#include "BehaviorTree/BehaviorTree.h"
AMonsterController::AMonsterController() {
static ConstructorHelpers::FObjectFinder<UBehaviorTree> ABT(TEXT("/Game/Resource/Character/Blueprints/AI/MonsterBT"));
if (ABT.Succeeded())
{
BT = ABT.Object;
}
static ConstructorHelpers::FObjectFinder<UBlackboardData> ABB(TEXT("/Game/Resource/Character/Blueprints/AI/MonsterBB"));
if (ABB.Succeeded())
{
BB = ABB.Object;
}
}
void AMonsterController::OnPossess(APawn* InPawn) {
Super::OnPossess(InPawn);
if (UseBlackboard(BB, Blackboard)) {
Blackboard->SetValueAsVector(FName(TEXT("CurrentVector")), InPawn->GetActorLocation());
RunBehaviorTree(BT);
}
}
//AIController, 간단하게 몬스터의 AI를 제어하는 컨트롤러다.
AMonster::AMonster()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
GetCapsuleComponent()->SetCapsuleHalfHeight(90.f);
GetCapsuleComponent()->SetCollisionProfileName(TEXT("Zombie"));
MaxHP = 50.f;
CurrentHP = MaxHP;
Armor = 5.f;
Damage = 5.f;
ConstructorHelpers::FObjectFinder<USkeletalMesh> Amesh(TEXT("/Game/Resource/Character/Zombie_M/zombie"));
if (Amesh.Succeeded()) {
GetMesh()->SetSkeletalMesh(Amesh.Object);
GetMesh()->SetRelativeLocationAndRotation(FVector(.0f, .0f, -89.f), FRotator(.0f, -90.0f, .0f));
}
static ConstructorHelpers::FClassFinder<UAnimInstance> AnAnim(TEXT("/Game/Resource/Character/Blueprints/Zombie_M/ZombieAnimation"));
if (AnAnim.Succeeded())
{
GetMesh()->SetAnimInstanceClass(AnAnim.Class);
}
AIControllerClass = AMonsterController::StaticClass();
AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned;
}
//AutoPossess는 빙의하는 조건.
//몬스터의 상황에 따라 다르겠지만, 우선적으로 모든 몬스터는 컨트롤러를 가지고 이는 것으로 시작한다.
#include "MonsterAnimInstance.h"
#include "Monster.h"
#include "Engine/Classes/GameFramework/CharacterMovementComponent.h"
UMonsterAnimInstance::UMonsterAnimInstance() {
Speed = 0.f;
IsJumping = false;
}
void UMonsterAnimInstance::NativeBeginPlay()
{
Super::NativeBeginPlay();
Owner = Cast<AMonster>(TryGetPawnOwner());
}
void UMonsterAnimInstance::NativeUpdateAnimation(float DeltaSeconds)
{
Super::NativeUpdateAnimation(DeltaSeconds);
if (Owner) {
Speed = Owner->GetVelocity().Size2D();
IsJumping = Owner->GetCharacterMovement()->IsFalling();
}
}
// 몬스터 애님인스턴스는 우선구현으로 조정.
SearchNextLocation라는 태스크 노드를 만들어 다음 목적지를 설정한다.
#include "SearchNextLocation.h"
#include "NavigationSystem.h"
#include "MonsterController.h"
#include "BehaviorTree/BlackboardComponent.h"
USearchNextLocation::USearchNextLocation() {
NodeName = TEXT("SearchNextLocation");
}
EBTNodeResult::Type USearchNextLocation::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) {
auto Owner = OwnerComp.GetAIOwner()->GetPawn();
if (Owner == nullptr) return EBTNodeResult::Failed;
auto NavSystem = UNavigationSystemV1::GetNavigationSystem(Owner->GetWorld());
if (NavSystem == nullptr) return EBTNodeResult::Failed;
FNavLocation NextLocation;
if (NavSystem->GetRandomPointInNavigableRadius(Owner->GetActorLocation(), 800.f, NextLocation)) {
OwnerComp.GetBlackboardComponent()->SetValueAsVector(TEXT("DestinationVector"), NextLocation.Location);
return EBTNodeResult::Succeeded;
}
return EBTNodeResult::Failed;
}
'게임프로그래밍 > TheZombie' 카테고리의 다른 글
게임 개발 - AI(3) (0) | 2022.02.05 |
---|---|
게임 개발 - AI(2) (0) | 2022.02.04 |
게임 개발 - UI(4) (0) | 2022.02.04 |
게임 개발 - UI(3) (0) | 2022.02.04 |
게임 개발 - UI(2), HP/SP (0) | 2022.02.04 |
댓글