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

내일배움캠프 55일차 TIL 2026/07/09

begin-play 2026. 7. 9. 21:31

TIL (Today I Learned) - 언리얼 투사체 스킬 시스템 확장

1. 데이터 기반 스킬 설계 (Data Driven Design)

오늘 구현한 투사체 스킬 시스템에서 가장 중요한 부분은 스킬 로직과 스킬 데이터를 분리하는 구조였다.

기존처럼 스킬마다 클래스를 따로 만들면:

FireballSkill
IceSkill
ArrowSkill
...
 

처럼 스킬 개수가 늘어날수록 코드 관리가 어려워진다.

그래서:

SkillData(DataTable)
        ↓
PlayerProjectileSkillBase
        ↓
PlayerProjectileBase
 

구조로 설계했다.


배운 점

스킬마다 달라지는 값:

  • 데미지
  • 투사체 속도
  • 폭발 여부
  • 폭발 범위
  • 투사체 개수
  • 발사 간격
  • 퍼지는 각도
  • 관통 횟수
  • 이동 거리
  • 삭제 방식

같은 값들은 코드가 아니라 데이터로 관리한다.

이를 통해 새로운 스킬을 추가할 때:

코드 수정 X
DataTable Row 추가 O
 

만으로 새로운 스킬 제작이 가능해진다.


2. Enum을 이용한 상태별 동작 분리

오늘 처음 Enum을 활용했다.

투사체 삭제 방식을 하나의 변수로 관리하기 위해:

 
enum class EProjectileDestroyType
{
    Distance,
    TargetLocation,
    LifeTime
};
 

를 사용했다.


Enum의 역할

단순한 숫자를 의미 있는 이름으로 관리한다.

예:

 
DestroyType = 0;
 

보다

 
DestroyType = EProjectileDestroyType::Distance;
 

가 코드 의미를 명확하게 만든다.


활용 방식

Tick에서:

 
switch(DestroyType)
{
case Distance:
    거리 체크

case TargetLocation:
    목표 위치 체크

case LifeTime:
    시간 체크
}
 

처럼 서로 다른 행동을 하나의 클래스로 처리할 수 있었다.


3. Line Trace (Raycast)를 이용한 마우스 클릭 위치 추적

마우스 클릭 위치를 얻기 위해 Line Trace를 사용했다.

처음에는:

 
TargetLocation =
PlayerLocation + WorldDirection * 3000;
 

방식으로 처리했다.

하지만 이것은:

카메라 방향
+
거리
 

일 뿐 실제 클릭한 바닥 위치가 아니다.


그래서:

마우스 좌표
      ↓
DeprojectScreenPositionToWorld
      ↓
World Direction
      ↓
Line Trace
      ↓
HitResult.Location
 

구조로 변경했다.


Line Trace란?

보이지 않는 선을 월드에 쏴서 충돌 지점을 찾는 기능이다.

활용 예:

  • 마우스 클릭 위치
  • 총알 조준
  • 적 탐색
  • 상호작용 위치 찾기
  • 바닥 위치 확인

등 게임 개발에서 매우 많이 사용된다.


4. 투사체 이동과 방향 벡터

투사체 방향은 Vector 계산으로 처리했다.

 
FVector Direction = TargetLocation - PlayerLocation;
 

두 위치의 차이를 구하면 방향 벡터가 된다.


그리고:

 
Direction.Normalize();
 

를 사용해 길이를 1로 만든다.

이유:

(100,0,0)
 

과

(1,0,0)
 

은 방향은 같지만 크기가 다르다.

Normalize하면 방향만 남는다.


최종 이동:

 
Velocity =
Direction * Speed;
 

구조로 처리했다.


5. 투사체 삭제 조건 설계

투사체 삭제 방법을 여러 방식으로 확장했다.

거리 기반 삭제

발사 위치
    ↓
일정 거리 이동
    ↓
Destroy()
 

사용 예:

  • 화살
  • 총알
  • 레이저

목표 위치 기반 삭제

발사 위치
    ↓
마우스 클릭 위치
    ↓
도착하면 Destroy()
 

사용 예:

  • 순간 폭발 투사체
  • 지정 위치 공격
  • 메테오

처음에는:

 
Distance(CurrentLocation, TargetLocation)
 

으로 접근했지만 빠른 투사체는 목표 위치를 지나칠 수 있었다.

그래서:

현재 이동 거리
>=
목표까지 이동 거리
 

방식으로 변경했다.


6. Tick과 프레임 기반 문제 이해

오늘 중요한 부분 중 하나.

게임은 연속적으로 움직이는 것처럼 보이지만 실제로는:

Frame 1
Frame 2
Frame 3
...
 

단위로 업데이트된다.

따라서:

현재 위치
↓
다음 Tick
↓
목표 위치 통과
 

가 발생할 수 있다.

이를:

Overshooting(목표 초과 이동)

이라고 한다.


해결 방법:

정확히 도착 여부를 보는 것이 아니라

 
현재 이동거리 >= 목표 이동거리
 

로 판단한다.


7. 디버그 시각화 활용

오늘 디버깅에서:

 
DrawDebugSphere()
 

를 사용했다.

기능 확인 시 로그만 보는 것보다:

  • 위치
  • 범위
  • 충돌 지점

을 직접 화면에서 확인하는 것이 훨씬 빠르다.

활용:

 
DrawDebugSphere()
DrawDebugLine()
DrawDebugBox()
 

등이 있다.


오늘 배운 핵심 정리

기술배운 내용
Data Driven Design 데이터와 로직 분리
DataTable 스킬 값을 외부 데이터로 관리
Enum 상태별 동작 분기
Vector 연산 방향 계산과 거리 계산
Normalize 방향 벡터 정규화
Line Trace 마우스 클릭 위치 찾기
Projectile Movement 속도 기반 투사체 이동
Tick 프레임 기반 업데이트 이해
Overshooting 빠른 이동에서 발생하는 문제
Debug Draw 위치와 충돌 시각화

오늘 구현한 최종 구조

Mouse Click
    ↓
Line Trace
    ↓
TargetLocation 획득
    ↓
SkillData 조회
    ↓
Projectile Spawn
    ↓
Initialize Direction
    ↓
MovementComponent 이동
    ↓
DestroyType 판단
    ↓
Distance / TargetLocation / LifeTime 처리