본문 바로가기
게임프로그래밍/TheZombie

게임 개발 - 몬스터, AI(1)

by 설련 2022. 2. 4.

 

전체적인 방향은 영상과 같다.

 

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

댓글