스킬 시스템 및 투사체 구조 구현
1. DataTable 기반 스킬 데이터 관리 구조 이해
오늘은 스킬 정보를 코드에 직접 작성하지 않고 DataTable을 통해 관리하는 구조를 구현했다.
기존 방식:
Damage = 10.0f;
Speed = 500.0f;
처럼 코드 내부에 값을 고정하면 스킬이 많아질수록 수정이 어렵다.
개선 방식:
FSkillData
{
SkillName,
Damage,
Cooldown,
ProjectileClass,
ProjectileSpeed,
ExplosionRadius,
DestroyType
}
와 같은 구조체를 만들고 DataTable(DT_SkillData)에서 데이터를 가져오는 방식으로 변경했다.
장점:
- 디자이너가 에디터에서 수치 수정 가능
- 새로운 스킬 추가 시 코드 수정 최소화
- 같은 스킬 로직을 다른 데이터로 재사용 가능
2. Actor와 Component 역할 분리
스킬 구현 과정에서 기능의 역할을 분리하는 구조를 학습했다.
Skill Component
스킬 실행을 담당하는 관리자 역할
예:
PlayerSkillComponent
|
↓
SkillData 검색
|
↓
Skill Actor 생성
Skill Actor
실제 게임 월드에서 동작하는 객체
예:
PlayerProjectileSkillBase
|
↓
Projectile Spawn
Projectile Actor
날아가는 투사체 자체
예:
PlayerProjectileBase
|
↓
Collision
Movement
Hit 처리
Destroy
각 클래스가 하나의 역할만 담당하도록 분리하는 것이 유지보수에 중요하다는 것을 배웠다.
3. 투사체 스킬 생성 흐름 분석
오늘 구현한 투사체 생성 과정:
플레이어 입력
↓
PlayerSkillComponent::UseSkill()
↓
SkillData 검색
↓
SkillClass 생성
↓
PlayerProjectileSkillBase::ExecuteSkill()
↓
Projectile Spawn
↓
PlayerProjectileBase 동작
즉, 입력부터 투사체가 생성될 때까지 데이터가 전달되는 흐름을 이해했다.
4. SpawnActor를 통한 런타임 객체 생성
언리얼에서는 에디터에 배치하지 않은 객체도 런타임에서 생성할 수 있다.
사용 방식:
GetWorld()->SpawnActor<AActor>(
SpawnClass,
Location,
Rotation
);
중요한 점:
SpawnActor는 클래스 정보가 필요하다.
그래서:
TSubclassOf<APlayerProjectileBase> ProjectileClass;
형태로 블루프린트 클래스 정보를 받아서 생성했다.
5. TSubclassOf와 Blueprint 연동 이해
C++에서:
UPROPERTY(EditAnywhere)
TSubclassOf<APlayerProjectileBase> ProjectileClass;
를 선언하면
블루프린트에서:
ProjectileClass
↓
BP_SonicVoltProjectile
같은 방식으로 연결 가능하다.
즉:
C++:
"투사체를 생성할 수 있는 타입을 받을 공간"
Blueprint:
"실제 생성할 투사체 지정"
역할 분리가 가능하다.
6. 투사체 초기화 패턴
생성 후 필요한 데이터를 전달하기 위해:
InitializeProjectile(Direction);
같은 초기화 함수를 사용하는 방식을 배웠다.
생성자에서는:
- 컴포넌트 생성
- 기본 설정
초기화 함수에서는:
- 방향
- 속도
- 데미지
- 이동 정보
같은 런타임 데이터를 전달한다.
구조:
SpawnActor()
|
↓
Projectile 생성
|
↓
InitializeProjectile()
|
↓
Movement 시작
7. Collision 문제 해결 과정
투사체 테스트 중 발생했던 문제:
Stack Overflow
Chaos Collision Error
원인은 코드가 아니라 충돌 설정이었다.
몬스터 Blueprint의 Static Mesh가:
Collision Preset = BlockAllDynamic
으로 설정되어 있어서 물리 충돌 계산이 과도하게 발생했다.
해결:
Static Mesh
Collision
↓
NoCollision
으로 변경.
배운 점:
언리얼 오류는 항상 코드 문제가 아니라
- Collision
- Physics
- Blueprint 설정
- Actor 관계
도 함께 확인해야 한다.
8. 로그를 통한 디버깅 방법
오늘 사용한 방식:
UE_LOG(LogTemp, Warning, TEXT("Projectile Spawn Success"));
로그를 통해 실행 흐름 확인.
확인했던 내용:
ProjectileClass NULL
→ 생성할 투사체 클래스가 지정되지 않음
Distance Mode
→ 투사체 제거 조건 로직 실행 확인
Projectile Data Damage: 10
Speed: 500
→ DataTable 데이터 정상 전달 확인
로그는 단순 출력이 아니라
데이터가 어느 단계까지 정상 전달되는지 확인하는 도구라는 것을 학습했다.
9. 스킬 확장 구조 설계
현재 구조:
SkillComponent
|
|
PlayerSkillBase
|
|
--------------------
| |
ProjectileSkill AreaSkill
|
|
Explosion
처럼 부모 클래스를 기준으로 확장 가능하도록 설계했다.
앞으로 추가 가능한 스킬:
- 투사체 공격
- 장판 공격
- 순간이동
- 범위 공격
- 버프 스킬
등을 같은 구조 안에서 추가할 수 있다.
오늘 배운 핵심 정리
1.
데이터(DataTable)와 로직(C++)을 분리하면 확장성이 좋아진다.
2.
Actor는 실제 동작하는 객체, Component는 기능 관리 역할로 분리한다.
3.
SpawnActor를 이용하면 런타임에 원하는 객체를 생성할 수 있다.
4.
TSubclassOf를 사용하면 C++과 Blueprint 사이에서 클래스를 연결할 수 있다.
5.
언리얼 디버깅은 코드뿐 아니라 Collision, Blueprint 설정까지 함께 확인해야 한다.
6.
좋은 구조는 새로운 기능을 추가할 때 기존 코드를 수정하지 않는 구조다.
오늘 구현 흐름 한 줄 정리
DataTable에서 스킬 데이터를 가져오고 → Skill Actor를 생성하고 → Skill Actor가 Projectile Actor를 Spawn하는 구조를 통해 확장 가능한 스킬 시스템의 기본 구조를 구현했다.
'내일배움캠프_언리얼9기' 카테고리의 다른 글
| 내일배움캠프 60일차 TIL 2026/07/16 (0) | 2026.07.16 |
|---|---|
| 내일배움캠프 59일차 TIL 2026/07/15 (0) | 2026.07.15 |
| 내일배움캠프 56일차 TIL 2026/07/10 (0) | 2026.07.10 |
| 내일배움캠프 55일차 TIL 2026/07/09 (0) | 2026.07.09 |
| 내일배움캠프 54일차 TIL 2026/07/08 (0) | 2026.07.08 |