💭회고
https://raindrovvv.tistory.com/18
[TIL250210_1] State Machine 설계를 통한 캐릭터 동작 애니메이션 적용
💭회고State Machine을 활용한 캐릭터 동작 애니메이션 적용에 대해 학습했다.특히 애니메이션 블루프린트의 개념, 캐릭터 이동 상태 감지, State Machine 설계를 중심으로 실습을 진행했다. 그리고 Ble
raindrovvv.tistory.com
스테이트 머신 애니메이션 설계하는 법에 이어서 인터페이스를 활용하여 아이템 시스템을 구축하는 방법을 학습했다.
처음에는 단순한 상속으로도 충분할 것 같았지만, 인터페이스를 활용하면 결합도를 낮추고, 확장성을 높일 수 있다는 점을 직접 구현하면서 실감했다. 실제 개발 과정에서 고려해야 할 사항들도 정리해 두었다.
🗺️마인드맵
📒학습 내용
1. 인터페이스란?
🔹 인터페이스(Interface) 개념
- 클래스가 반드시 구현해야 할 함수 목록을 미리 정의한 일종의 계약서
- 함수의 구현 내용은 이를 상속받는 클래스에서 자유롭게 정의 가능
- 언리얼 엔진에서는 UInterface 를 통해 구현할 수 있다.
🔹 상속과의 차이점
// ✅ 상속: 부모 클래스의 기능을 그대로 사용
class Child : public Parent {
// 부모 함수 사용 가능
};
// ✅ 인터페이스: 함수 형태만 정의, 직접 구현해야 함
class Item : public IItemInterface {
// 인터페이스의 함수 직접 구현 필수
};
언리얼 코드 컨벤션 상, 인터페이스의 cpp 파일은 사용하지 않더라도 삭제하면 안 된다!
헤더와 소스 파일은 한 쌍으로 관리하는 것이 원칙이다.
💡 인터페이스를 사용하면 좋은 점
✅ 결합도 감소: 특정 클래스에 의존하지 않음
✅ 확장성 향상: 새로운 아이템 추가가 쉽다
✅ 다형성 활용: TArray<IItemInterface*> Items; 처럼 인터페이스 포인터 배열로 다양한 아이템을 통합 관리
2. 아이템 시스템 구현
2.1 인터페이스 정의
인터페이스를 설계할 때, 추후 확장될 기능까지 고려해야 한다!
#pragma once
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "IItemInterface.generated.h"
UINTERFACE(MinimalAPI)
class UItemInterface : public UInterface
{
GENERATED_BODY()
};
class SPARTAPROJECT_API IItemInterface
{
GENERATED_BODY()
public:
virtual void OnItemOverlap(AActor* OverlapActor) = 0;
virtual void OnItemEndOverlap(AActor* OverlapActor) = 0;
virtual void ActivateItem(AActor* Activator) = 0;
virtual FName GetItemType() const = 0;
};
📌 핵심 개념
- 모든 아이템이 공통적으로 가져야 할 기능을 정의 (오버랩 감지, 사용, 타입 반환)
- = 0; 👉 순수 가상 함수 (Pure Virtual Function) 로 반드시 구현해야 함
- AActor* 타입을 사용한 이유?
- 기획 변경 가능성을 염두! (예: 플레이어뿐만 아니라 몬스터도 아이템을 획득 가능)
- FName을 사용하는 이유?
- FString보다 훨씬 빠르고 메모리 사용이 효율적이라 타입 반환만 필요할 때 쓰임!
2.2 기본 아이템 클래스 BaseItem 구현
아이템 계층 구조를 미리 설계해야 한다!
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ItemInterface.h"
#include "BaseItem.generated.h"
UCLASS()
class SPARTARPROJECT_API ABaseItem : public AActor, public IItemInterface
{
GENERATED_BODY()
public:
ABaseItem();
protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
FName ItemType;
virtual void OnItemOverlap(AActor* OverlapActor) override;
virtual void OnItemEndOverlap(AActor* OverlapActor) override;
virtual void ActivateItem(AActor* Activator) override;
virtual FName GetItemType() const override;
virtual void DestroyItem();
};
✅ BaseItem을 만들어 공통 로직을 한 곳에 정리
✅ DestroyItem() 함수를 추가하여, 아이템이 제거될 때 추가적인 효과(이펙트, 사운드 등) 쉽게 적용 가능
3. 아이템 클래스 구현
3.1 코인 아이템 (BigCoin & SmallCoin)🪙
#pragma once
#include "CoreMinimal.h"
#include "BaseItem.h"
#include "CoinItem.generated.h"
UCLASS()
class SPARTARPROJECT_API ACoinItem : public ABaseItem
{
GENERATED_BODY()
public:
ACoinItem();
protected:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
int32 PointValue;
};
#include "CoinItem.h"
ACoinItem::ACoinItem()
{
// 부모 생성자 로직 (필요 시)
}
- `PointValue`는 `UPROPERTY`로 선언했기 때문에, 에디터에서 값을 수정하거나 블루프린트로 접근 가능.
- `CoinItem` 자체는 직접 사용하기보다는, 구체적인 아이템 (BigCoin, SmallCoin)의 부모 클래스로 활용.
🔹 BigCoin 아이템 구현
#include "BigCoinItem.h"
ABigCoinItem::ABigCoinItem()
{
PointValue = 50;
ItemType = "BigCoin";
}
void ABigCoinItem::ActivateItem(AActor* Activator)
{
DestroyItem();
}
#include "BigCoinItem.h"
ABigCoinItem::ABigCoinItem()
{
PointValue = 50;
ItemType = "BigCoin";
}
void ABigCoinItem::ActivateItem(AActor* Activator)
{
DestroyItem(); //아이템 소멸(부모의 DestroyItem() 혹은 자체 로직)
}
✅ 구조가 동일한 아이템이라면, 부모 클래스(CoinItem)에서 공통 로직을 처리!
🎯 깨달은 점
1. BaseItem 없이 만들었다면, 중복 코드가 반복되었을 것!
2. Override하는 방식이 다양한 아이템을 유연하게 구현하는 핵심 요소
3.2 지뢰 아이템 MineItem💣
BaseItem을 상속받는다.
- 지뢰 아이템 (MineItem)은 설치된 후, 일정 시간이 지나면 폭발하여 주변에 피해를 준다.
- 폭발 범위와 폭발 데미지 등은 변수로 관리한다.
#pragma once
#include "CoreMinimal.h"
#include "BaseItem.h"
#include "MineItem.generated.h"
UCLASS()
class SPARTARPROJECT_API AMineItem : public ABaseItem
{
GENERATED_BODY()
public:
AMineItem();
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Mine")
float ExplosionDelay;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Mine")
float ExplosionRadius;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Mine")
float ExplosionDamage;
virtual void ActivateItem(AActor* Activator) override;
};
#include "MineItem.h"
AMineItem::AMineItem()
{
ExplosionDelay = 5.0f;
ExplosionRadius = 300.0f;
ExplosionDamage = 30.0f;
ItemType = "Mine";
}
void AMineItem::ActivateItem(AActor* Activator)
{
// 실제로는 지연 시간 후 폭발 로직을 구현하거나 폭발 이펙트, 데미지 계산 등을 추가할 수 있음
DestroyItem();
}
✅ ExplosionDelay, ExplosionRadius, ExplosionDamage 속성을 추가하여 폭발 아이템 구현 가능
✅ ActivateItem()에서 폭발 애니메이션, 데미지 처리 등을 추가하면 더욱 현실적인 연출 가능!
3.3 힐링 아이템 HealingItem❤️🩹
#pragma once
#include "CoreMinimal.h"
#include "BaseItem.h"
#include "HealingItem.generated.h"
UCLASS()
class SPARTARPROJECT_API AHealingItem : public ABaseItem
{
GENERATED_BODY()
public:
AHealingItem();
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Item")
float HealAmount;
virtual void ActivateItem(AActor* Activator) override;
};
#include "HealingItem.h"
AHealingItem::AHealingItem()
{
HealAmount = 20.0f;
ItemType = "Healing";
}
void AHealingItem::ActivateItem(AActor* Activator)
{
DestroyItem();
}
- MineItem, HealingItem처럼 전혀 다른 동작을 하는 아이템들도 같은 함수 이름 (ActivateItem)으로 제어 가능!
🟣오늘의 옵시디언 현황
'Dev. > UE 언리얼 엔진' 카테고리의 다른 글
[TIL_250211_2] 충돌 이벤트를 활용한 아이템 획득 시스템 구현하기 (0) | 2025.02.11 |
---|---|
[TIL_250211_1] 머티리얼 시스템 이해 (기초) #Graphics (1) | 2025.02.11 |
[TIL250210_1] State Machine 설계를 통한 캐릭터 동작 애니메이션 적용 (0) | 2025.02.10 |
[TIL_250203] EnhancedInputSystem으로 입력 매핑, 캐릭터 동작 구현하기 (0) | 2025.02.03 |
[TIL_250131] Character 클래스를 활용한 캐릭터 구현하기(3인칭 카메라 설정, GameMode 설정) (0) | 2025.01.31 |