Unreal
[Unreal C++] 액터 컴포넌트 만들기
푸쿠이
2021. 5. 10. 16:06
참고 자료
'이득우의 언리얼 C++ 게임 개발의 정석' Chapter 11
&
액터 컴포넌트란?
계층 구조를 가지는 컴포넌트는 Scene Component이다.
기능만 가지는 컴포넌트는 Actor Component이다.
블루프린트 창에서 보면 이렇게 구분된다.
액터 컴포넌트 제작하기
이 게시글에서 제작할 액터 컴포넌트는 Character Stat을 관리하는 컴포넌트이다.
기능을 독립적으로 만들어야 관리하기에 쉽다.
Actor Component를 부모 클래스로 상속받아 클래스를 만든다.
클래스를 만들고 컴파일이 완료되면, 컴포넌트로써 추가할 수 있게 된다.
CharacterStatComponent.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "ArenaBattle.h"
#include "Components/ActorComponent.h"
#include "ABCharacterStatComponent.generated.h"
UCLASS( ClassGroup=(Custom), meta=(BlueprintSpawnableComponent) )
class ARENABATTLE_API UABCharacterStatComponent : public UActorComponent
{
GENERATED_BODY()
public:
UABCharacterStatComponent();
protected:
virtual void BeginPlay() override;
virtual void InitializeComponent() override;
public:
void SetNewLevel(int32 NewLevel);
float GetAttack();
private:
struct FABCharacterData* CurrentStatData = nullptr;
UPROPERTY(EditInstanceOnly, Category = Stat, Meta = (AllowPrivateAccess = true))
int32 Level;
UPROPERTY(Transient, VisibleInstanceOnly, Category = Stat, Meta = (AllowPrivateAccess = true)) // Transient : 직렬화에서 제외.
float CurrentHP;
};
CharacterStatComponent.cpp
이전 게시글에서 했던 GameInstance에 데이터 테이블 값을 저장해놓은 것을 사용했다.
2021.05.10 - [게임 엔진/[Unreal] Engine] - [Unreal C++] 데이터 테이블 만들고, 사용하기 (CSV 파일)
#include "ABCharacterStatComponent.h"
#include "ABGameInstance.h"
#include "CustomDataTables.h"
UABCharacterStatComponent::UABCharacterStatComponent()
{
PrimaryComponentTick.bCanEverTick = false; // Tick 함수 안 쓰니까 false로.
bWantsInitializeComponent = true; // 이걸 true해야 InitializeComponent 함수가 호출됨.
Level = 1;
}
void UABCharacterStatComponent::BeginPlay()
{
Super::BeginPlay();
}
void UABCharacterStatComponent::InitializeComponent()
{
Super::InitializeComponent();
SetNewLevel(Level);
}
void UABCharacterStatComponent::SetNewLevel(int32 NewLevel)
{
UABGameInstance* ABGameInstance = Cast<UABGameInstance>(UGameplayStatics::GetGameInstance(GetWorld()));
if (nullptr == ABGameInstance) return;
CurrentStatData = ABGameInstance->GetABCharacterData(NewLevel);
if (CurrentStatData)
{
Level = NewLevel;
CurrentHP = CurrentStatData->MaxHP;
}
else
{
UE_LOG(LogClass, Warning, TEXT("Level %d data doesn't exist."), NewLevel);
}
}
float UABCharacterStatComponent::GetAttack()
{
if (nullptr == CurrentStatData) return 0.0f;
return CurrentStatData->Attack;
}
이렇게 액터 컴포넌트에 기능을 구현했으면, 캐릭터에서 컴포넌트를 추가해서 사용하면 된다.
캐릭터 클래스
제작한 액터 컴포넌트를 추가해서 사용한다.
// 헤더
UPROPERTY(VisibleAnywhere, Category = Stat)
class UABCharacterStatComponent* CharacterStat;
// CPP
CharacterStat = CreateDefaultSubobject<UABCharacterStatComponent>(TEXT("CHARACTERSTAT"));
공격하는 곳에서 StatComponent의 Attack 함수를 통해 데미지를 받아올 수 있도록 구현한다.
if (bResult)
{
if (HitResult.Actor.IsValid())
{
UE_LOG(LogClass, Warning, TEXT("Hit Actor Name : %s"), *HitResult.Actor->GetName());
FDamageEvent DamageEvent;
HitResult.Actor->TakeDamage(CharacterStat->GetAttack(), DamageEvent, GetController(), this);
}
}