언리얼엔진(UE)

[UE] 몬스터 AI 구현 #4 (몬스터 기본 클래스 구성)

2h1824 2025. 2. 26. 21:54

1. 클래스 전체 구성

  • 공통적인 기본적인 구성 요소를 담는 BaseEnemy 
    ex) HP, Score, 사망 처리 함수 등
  • BaseEnemy를 상속하여 서로 다른 유형의 공격을 하는 Melee, Ranged 로 Enemy 분류

2. BaseEnemy

BaseEnemy.h

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "BaseEnemy.generated.h"

UCLASS()
class STARHUNT_API ABaseEnemy : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	ABaseEnemy();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	// Score
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Score")
	int32 Score;

	// Max Health
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health")
	float MaxHealth;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health")
	float Health;
	// Get health variables
	UFUNCTION(BlueprintPure, Category = "Health")
	float GetHealth() const;
	UFUNCTION(BlueprintPure, Category = "Health")
	float GetMaxHealth() const;

	// Healing
	UFUNCTION(BlueprintCallable, Category = "Health")
	void AddHealth(float Amount);

	// Death handling function
	UFUNCTION(BlueprintCallable, Category = "Health")
	virtual void OnDeath();

	// Damage handling function
	virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;
public:	
	// Called every frame
	//virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	//virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

};

BaseEnemy.cpp

// Fill out your copyright notice in the Description page of Project Settings.
// Copyright Epic Games, Inc. All Rights Reserved.

#include "BaseEnemy.h"
#include "EnemyAIController.h"

// Sets default values
ABaseEnemy::ABaseEnemy()
{
 	// 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;
	AIControllerClass = AEnemyAIController::StaticClass();
	AutoPossessAI = EAutoPossessAI::PlacedInWorldOrSpawned;
}

// Called when the game starts or when spawned
void ABaseEnemy::BeginPlay()
{
	Super::BeginPlay();
	
}

float ABaseEnemy::GetHealth() const
{
	return Health;
}

float ABaseEnemy::GetMaxHealth() const
{
	return MaxHealth;
}

void ABaseEnemy::AddHealth(float Amount)
{
	Health = FMath::Clamp(Health + Amount, 0.0f, MaxHealth);
}

void ABaseEnemy::OnDeath()
{
	// Deliver Score to Game Instance

	Destroy();
}

float ABaseEnemy::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
	float ActualDamage = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);

	Health = FMath::Clamp(Health - DamageAmount, 0.0f, MaxHealth);
	if (Health <= 0.0f) 
	{
		OnDeath();
	}
	return ActualDamage;
}
  • Health, MaxHealth, Score 등의 공통 변수 및 함수 선언
  • 사망 처리를 할때 공통 수행할 동작을 선언 및 정의
  • TakeDamage 함수를 override하여 재정의
  • AI 컨트롤러 클래스 설정 및 연결
  • AI가 캐릭터를 자동 조종 ㅡ> Placed in World or Spawned (월드 배치 or 게임 중 스폰)

3. EnemyAIController

EnemyAIController.h

// Fill out your copyright notice in the Description page of Project Settings.
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once

#include "CoreMinimal.h"
#include "AIController.h"
#include "EnemyAIController.generated.h"

/**
 * 
 */
UCLASS()
class STARHUNT_API AEnemyAIController : public AAIController
{
	GENERATED_BODY()
	
public:
	virtual void OnPossess(APawn* InPawn) override;
	virtual void BeginPlay() override;
	virtual void OnMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult& Result) override;

};

EnemyAIController.cpp

// Fill out your copyright notice in the Description page of Project Settings.
// Copyright Epic Games, Inc. All Rights Reserved.

#include "EnemyAIController.h"
#include "GameFramework/Character.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/NavMovementComponent.h"

void AEnemyAIController::OnPossess(APawn* InPawn)
{
	Super::OnPossess(InPawn);

	// Use Acceleration when move along path (associated with Animation)
	ACharacter* Character = Cast<ACharacter>(InPawn);
	if (Character)
	{
		UCharacterMovementComponent* MovementComp = Character->GetCharacterMovement();
		if (MovementComp)
		{
			MovementComp->bRequestedMoveUseAcceleration=true;
		}
	}
}

void AEnemyAIController::BeginPlay()
{
	Super::BeginPlay();
}

void AEnemyAIController::OnMoveCompleted(FAIRequestID RequestID, const FPathFollowingResult& Result)
{
	Super::OnMoveCompleted(RequestID, Result);
}
  • AI가 폰에 Possess 되었을 때 호출되는 함수를 재정의하여 부모 클래스의 원본 함수를 호출
  • 추가로 빙의된 캐릭터 클래스의 CharacterMovementComponent의 움직일 때 가속도를 사용하도록 설정
    ㅡ> 해당 옵션 체크하지 않을 시 가속도가 반영되지 않아 캐릭터의 애니메이션 오작동 발생 가능성이 있음

4. Health, MaxHealth, Score 변수 값 초기화

MeleeEnemy.cpp

// Fill out your copyright notice in the Description page of Project Settings.
// Copyright Epic Games, Inc. All Rights Reserved.

#include "MeleeEnemy.h"

AMeleeEnemy::AMeleeEnemy()
{
	Score = 100;
	Health = 500;
	MaxHealth = Health;
}

RangedEnemy.cpp

// Fill out your copyright notice in the Description page of Project Settings.
// Copyright Epic Games, Inc. All Rights Reserved.

#include "RangedEnemy.h"

ARangedEnemy::ARangedEnemy()
{
	Score = 150;
	Health = 300;
	MaxHealth = Health;
}
  • 실질적으로 사용되는 Enemy 클래스의 생성자에서 변수들의 값 초기화

5. 정리

완료

  • 기본적인 설정 완료

예정

  • AI가 어떤 행동을 할지 결정하는 BehaviorTree 및 관련 변수가 저장되는 BlackBorad 생성 및 구성
  • 그 외 Melee, Ranged Enemy 클래스나 Base에서 필요한 함수 및 변수 생성, 초기화
  • HP 바 위젯 
  • 순찰 및 공격 + 데미지 시스템

 


참고자료

X