내일배움캠프_언리얼9기

내일배움캠프 61일차 TIL 2026/07/20

begin-play 2026. 7. 20. 23:53

Unreal Engine DataTable을 활용한 플레이어 스킬 데이터 기반 시스템 구현

1. 구현 목표

플레이어의 스킬을 각각 별도의 코드로 하드코딩하지 않고, Unreal Engine의 DataTable을 이용해 스킬의 설정값을 데이터로 관리하는 시스템을 구현했다.

스킬마다 다음과 같은 값이 달라질 수 있다.

  • 데미지
  • 투사체 속도
  • 투사체 개수
  • 투사체 발사 각도
  • 관통 횟수
  • 폭발 여부 및 범위
  • 유도탄 여부
  • 투사체 소멸 방식
  • 장판 생성 여부
  • 대시 거리와 속도

이러한 값을 코드에 직접 작성하는 대신 DataTable의 행(Row)에 저장하고, 스킬을 사용할 때 해당 데이터를 읽어 스킬을 생성하도록 구성했다.

즉, 스킬의 공통적인 실행 로직은 C++에서 처리하고, 스킬마다 달라지는 수치와 설정은 DataTable에서 관리하는 구조이다.


2. DataTable 행 구조체 만들기

DataTable에서 사용할 행은 FTableRowBase를 상속받는 구조체로 작성해야 한다.

 
USTRUCT(BlueprintType)
struct FSkillData : public FTableRowBase
{
	GENERATED_BODY()
 

FSkillData는 DataTable의 한 행에 해당한다.

예를 들어 DataTable에 다음과 같은 Row를 만들 수 있다.

Row NameSkillNameDamageProjectileSpeedPierceCount
FireBall FireBall 10 1000 0
IceShot IceShot 20 700 3
HomingMissile HomingMissile 30 500 0

이렇게 하면 각 스킬의 차이점을 코드에 직접 작성하지 않고 DataTable의 Row 데이터만 변경하여 조절할 수 있다.


3. 스킬 클래스와 데이터의 분리

 
TSubclassOf<APlayerSkillBase> SkillClass;
TSubclassOf<APlayerProjectileBase> ProjectileClass;
 

여기서 중요한 점은 스킬의 실행 코드와 스킬의 설정 데이터를 분리했다는 것이다.

예를 들어 FSkillData에는 다음과 같은 정보가 들어갈 수 있다.

스킬 이름
↓
어떤 스킬 클래스인가?
↓
어떤 투사체를 사용하는가?
↓
데미지는 얼마인가?
↓
속도는 얼마인가?
↓
폭발하는가?
↓
유도탄인가?
 

따라서 같은 스킬 실행 코드를 사용하더라도 DataTable의 설정값을 다르게 지정하면 서로 다른 스킬을 만들 수 있다.

예를 들어 같은 투사체 스킬 시스템을 사용하더라도:

FireBall
- Damage = 10
- Speed = 1000
- Explosion = false

Rocket
- Damage = 30
- Speed = 500
- Explosion = true
- ExplosionRadius = 300

HomingMissile
- Damage = 20
- Homing = true
- HomingDetectRange = 1000
 

처럼 설정할 수 있다.

이 구조의 핵심은 다음과 같다.

스킬의 동작 방식은 C++에서 구현하고, 스킬의 세부 설정은 DataTable에서 관리한다.


4. 하나의 데이터 구조체로 여러 종류의 스킬 지원

FSkillData에는 단순한 투사체 스킬뿐만 아니라 여러 가지 스킬의 설정값이 포함되어 있다.

투사체 소멸 방식

 
UENUM(BlueprintType)
enum class EProjectileDestroyType : uint8
{
	Distance,
	TargetLocation,
	LifeTime
};
 

투사체가 언제 사라질지를 Enum으로 관리한다.

Distance

최대 이동 거리만큼 이동하면 소멸한다.

 
float MaxTravelDistance;
 

TargetLocation

목표 위치에 도착하면 소멸한다.

LifeTime

일정 시간이 지나면 소멸한다.

 
float LifeTime;
 

이렇게 하면 투사체의 소멸 로직을 각각 별도로 만들 필요 없이, DataTable의 DestroyType 값에 따라 동작을 결정할 수 있다.


5. 하나의 투사체로 다양한 스킬 구현

 
float Damage;
float ProjectileSpeed;
int32 ProjectileCount;
float ProjectileFireInterval;
float SpreadAngle;
int32 PierceCount;
 

이러한 값을 DataTable에서 관리하면 하나의 투사체 시스템으로 여러 종류의 스킬을 구현할 수 있다.

예를 들어:

단일 투사체

ProjectileCount = 1
SpreadAngle = 0
 

여러 발 발사

ProjectileCount = 5
SpreadAngle = 30
 

산탄 형태

ProjectileCount = 7
SpreadAngle = 60
 

관통 투사체

PierceCount = 3
 

즉, 새로운 스킬을 만들 때마다 새로운 C++ 클래스를 추가하는 것이 아니라, 기존 시스템이 지원하는 범위 내에서는 DataTable의 값만 변경하여 새로운 스킬을 만들 수 있다.


6. 폭발 스킬 설정

 
bool bExplodeOnHit;
float ExplosionDamage;
float ExplosionRadius;
 

투사체가 충돌했을 때 폭발하는지 여부와 폭발 범위를 데이터로 관리한다.

예를 들어:

bExplodeOnHit = true
ExplosionDamage = 30
ExplosionRadius = 300
 

이면 투사체가 충돌한 위치를 기준으로 범위 공격을 실행할 수 있다.

반대로:

bExplodeOnHit = false
 

이면 일반적인 단일 투사체처럼 동작한다.

따라서 하나의 투사체 시스템이:

일반 투사체
+
폭발 투사체
+
관통 투사체
+
다중 발사 투사체
 

로 확장될 수 있다.


7. 유도탄 시스템 데이터화

 
bool bUseHoming;
float HomingStrength;
float HomingDetectRange;
float HomingStartDelay;
 

유도탄에 필요한 설정도 DataTable에서 관리하도록 구현했다.

bUseHoming
 

유도 기능을 사용할지 결정한다.

HomingStrength
 

목표를 향해 방향을 전환하는 힘을 설정한다.

HomingDetectRange
 

유도 대상 탐색 범위를 설정한다.

HomingStartDelay
 

발사 직후 바로 유도할지, 일정 시간 후 유도를 시작할지 결정한다.

예를 들어:

일반 투사체
bUseHoming = false
 
유도탄
bUseHoming = true
HomingStrength = 10
HomingDetectRange = 1000
HomingStartDelay = 0.5
 

처럼 같은 투사체 시스템에 데이터를 주입하여 서로 다른 동작을 만들 수 있다.


8. 장판 스킬도 데이터로 분리

 
bool bIsAreaSkill;
EAreaSpawnType AreaSpawnType;
FName AreaDataRowName;
 

장판 스킬 역시 데이터 기반으로 관리했다.

먼저:

 
bIsAreaSkill
 

을 통해 해당 스킬이 장판 스킬인지 판단한다.

그 다음:

 
EAreaSpawnType
 

을 통해 장판이 생성되는 위치를 결정한다.

 
enum class EAreaSpawnType : uint8
{
	TargetLocation,
	ProjectileHit
};
 

TargetLocation

플레이어가 클릭한 위치에 장판 생성

플레이어
    ↓
클릭 위치
    ↓
장판 생성
 

ProjectileHit

투사체가 충돌한 위치에 장판 생성

투사체
    ↓
충돌
    ↓
충돌 위치에 장판 생성
 

또한:

 
FName AreaDataRowName;
 

을 사용해 별도의 DT_AreaData에서 장판의 상세 데이터를 가져오도록 구성했다.

따라서 스킬 데이터와 장판 데이터를 분리하여 관리할 수 있다.

DT_SkillData
    ↓
이 스킬은 장판을 사용하는가?
    ↓
어떤 장판 데이터를 사용할 것인가?
    ↓
DT_AreaData
    ↓
장판의 지속시간, 범위, 데미지 등 읽기
 

9. 대시 스킬도 같은 DataTable에서 관리

 
float DashDistance;
float DashSpeed;
float DashHitRadius;
float DashEndExplosionRadius;
float DashEndExplosionDamage;
 

대시 스킬에 필요한 값도 같은 FSkillData에서 관리한다.

예를 들어:

DashDistance = 500
DashSpeed = 2000
DashHitRadius = 100
DashEndExplosionRadius = 300
DashEndExplosionDamage = 50
 

이런 식으로 데이터만 설정하면 대시 공격의 특성을 변경할 수 있다.

이 구조를 통해:

투사체 스킬
장판 스킬
대시 스킬
 

을 하나의 스킬 데이터 시스템 안에서 관리할 수 있었다.


10. DataTable 기반 구조의 장점

이번 시스템의 가장 큰 장점은 스킬 데이터와 스킬 실행 로직의 분리이다.

기존의 하드코딩 방식이라면:

 
if (SkillName == "FireBall")
{
	Damage = 10;
	Speed = 1000;
}
else if (SkillName == "Rocket")
{
	Damage = 30;
	Speed = 500;
}
 

처럼 스킬이 늘어날 때마다 코드가 증가하게 된다.

하지만 DataTable을 사용하면:

SkillData
    ↓
DataTable에서 Row 검색
    ↓
스킬 데이터 가져오기
    ↓
스킬 실행 로직에 전달
    ↓
데이터에 맞게 스킬 생성
 

의 구조가 된다.

따라서 새로운 스킬을 추가할 때:

1. DataTable에 새로운 Row 추가
2. 스킬 클래스 또는 투사체 클래스 지정
3. 필요한 수치 설정
 

만으로 새로운 스킬을 만들 수 있다.


11. 이번 구현에서 배운 핵심

이번 작업을 통해 단순히 DataTable을 사용하는 방법뿐만 아니라, 데이터 중심 설계(Data-Driven Design) 방식에 대해 이해할 수 있었다.

스킬을 만들 때 모든 스킬을 각각 별도의 코드로 만드는 것이 아니라:

공통 로직
    +
DataTable의 설정값
 

으로 조합하는 방식이다.

예를 들어:

공통 투사체 시스템
        +
데미지
        +
속도
        +
관통 횟수
        +
폭발 여부
        +
유도 여부
        ↓
서로 다른 스킬 생성
 

결과적으로 새로운 스킬을 추가할 때 기존 코드를 크게 수정하지 않고도 DataTable의 데이터를 추가하거나 수정하여 스킬을 확장할 수 있는 구조를 구현했다.

 

한 줄 요약

Unreal Engine의 DataTable을 활용하여 스킬의 실행 로직과 스킬별 설정 데이터를 분리하고, 하나의 공통 스킬 시스템에서 투사체·폭발·관통·유도·장판·대시 등 다양한 스킬을 데이터 설정만으로 확장할 수 있도록 구현했다.