언리얼 엔진/TIL

TIL - 본캠프 2일차

journey46110 2026. 6. 29. 17:54

I. Blueprint - FPS 슈팅 게임 개발 세션 (2회차)

개요

오늘은 FPS 블루프린트 라이브 세션 2회차를 진행했다. 지난 시간에 구성한 1인칭 캐릭터에 총기를 장착하고, 발사를 위한 기본 구조를 만드는 작업을 진행했다. 총을 캐릭터의 손에 부착하는 두 가지 방법을 학습했고, 총알이 발사될 위치를 지정하는 MuzzlePoint를 추가했다. 또한 체력, 탄약, 공격력 등 FPS 게임에서 자주 사용하는 변수들을 생성했으며, Enhanced Input을 이용해 조준(Aim) 입력을 구현하는 과정도 학습했다. 구현 과정에서 단순히 기능을 따라 만드는 것뿐만 아니라 왜 이러한 방식으로 구현하는지에 대해 고민하며 기존에 배웠던 내용과 비교해 이해를 넓힐 수 있었다.

 

구현 과정

1) 총기 소켓 생성 및 장착

먼저 SK_Mannequin_Arms의 hand_r 본에 hand_r 소켓을 생성하고, 프리뷰 에셋으로 SM_M16_Scope를 연결하여 총기의 위치와 회전을 조정했다.

hand_r소켓

이후 실제 게임에서 총을 손에 부착하는 방법을 두 가지 방식으로 구현했다.

 

① Construction Script에서 Attach Component to Component 노드를 사용하는 방식

Attach Component To Component

처음에는 부모 컴포넌트와 소켓의 역할이 헷갈렸지만, 부모를 Mesh로 지정하고 Socket Name에 hand_r소켓을 입력하면 해당 소켓 위치에 총기가 자동으로 부착된다는 것을 이해했다. 또한 Location, Rotation, Scale Rule을 모두 Snap to Target으로 변경하여 소켓의 위치와 회전을 그대로 따라가도록 설정했다.

 

② Gun 컴포넌트를 카메라의 자식에서 Mesh의 자식으로 변경 후 부모 소켓을 hand_r로 지정하고 Transform을 초기화하는 방식

Gun 컴포넌트의 부모 소켓 지정

두 방법 모두 동일한 결과를 만들지만, 하나는 블루프린트에서 부착을 수행하고 다른 하나는 컴포넌트 계층 구조를 이용하는 방식이라는 차이를 이해했다.

 

2) MuzzlePoint 추가

총기의 자식으로 Scene Component를 추가하고 이름을 MuzzlePoint로 변경했다.

Character
 ├─ Camera
 ├─ Mesh
 └─ Gun
      └─ MuzzlePoint
MuzzlePoint의 위치

MuzzlePoint는 총알이 실제로 발사되는 기준 위치 역할을 한다. 총의 중심이 아닌 총구 끝에서 총알이나 이펙트가 생성되어야 자연스러운 표현이 가능하기 때문에 별도의 Scene Component를 사용하는 것이다. 앞으로 Spawn Actor나 Line Trace를 사용할 때 시작 위치로 활용될 예정이다.

 

3) FPS 기본 변수 생성

FPS 구현에 필요한 변수들도 함께 생성했다.

Health / MaxHealth 현재 체력 / 최대 체력
CurrentAmmo / MaxAmmo 현재 탄약 / 최대 탄약
BaseDamage 총기의 기본 공격력
FireInterval 연사 속도
IsFiring 발사 중 여부
CanFire 발사 가능한 상태 확인

현재 체력이나 탄약 수를 표시하기 위한 UI를 만들거나 최대 체력 상승 혹은 최대 탄약 상승과 같은 이벤트를 만들기 위해서 Health와 Ammo를 두 가지씩 따로 만들어서 관리한다.

 

4) 이동 입력 구현

기존에 정리한 IA(Input Action), IMC(Input Mapping Context)를 이용하여 캐릭터 이동과 시점 회전 입력을 연결하였다.

IA와 IMC 매핑

강의에서는 이동 방향을 계산할 때 Get Actor Forward Vector와 Get Actor Right Vector를 사용했다.

Get Actor Right Vector, Get Actor Forward Vector 사용

기존 베이스캠프에서는 Get Control Rotation을 이용하여 방향 벡터를 계산했기 때문에 두 방법의 차이가 궁금했다.
비교해 본 결과,

  • FPS에서는 카메라와 캐릭터가 항상 같은 방향을 바라보기 때문에 Get Actor Forward Vector를 사용해도 동일한 결과가 나온다.
  • TPS에서는 카메라와 캐릭터가 서로 다른 방향을 바라볼 수 있기 때문에 Get Control Rotation을 이용하여 카메라 기준으로 이동 방향을 계산하는 경우가 많다.

즉,

FPS
카메라 방향 = 캐릭터 방향

TPS
카메라 방향 ≠ 캐릭터 방향
 

이라는 차이를 이해하게 되었다.

 

5) Character 회전 설정

FPS에 맞는 회전 방식도 설정했다.

Controller Yaw, Controller Pitch 사용

Use Controller Rotation Pitch : On
Use Controller Rotation Yaw   : On
Orient Rotation to Movement   : Off
Camera - Use Pawn Control Rotation : Off
 

처음에는 Use Pawn Control Rotation을 끄는 이유가 이해되지 않았지만, 입력 이벤트에서 Add Controller Yaw Input과 Add Controller Pitch Input을 사용하여 Controller의 회전을 변경하고, Character가 Controller Rotation을 따라 회전하기 때문에 Camera도 부모인 Character를 따라 함께 회전하는 구조라는 것을 이해했다.

 

6) 조준(Aim) 입력 구현

IA_Aim을 생성하고 Value Type을 Digital(Bool)로 설정한 뒤, IMC에 마우스 우클릭으로 매핑했다.

강의에서는

Started
    ↓
Set IsAiming
(Not Boolean)
    ↓
Branch
 

구조를 사용했다.

나는 처음에는 단순히 조준과 일반 상태를 번갈아 출력하기 위해

Started
    ↓
FlipFlop
 

을 사용하여 구현했다.

기능 자체는 동일하게 동작했지만, 이후 사망이나 리스폰, 무기 교체, 재장전 등의 상황을 생각해 보니 FlipFlop은 현재 상태를 저장하지 못한다는 문제가 있었다.

반면 IsAiming이라는 Boolean 변수를 사용하면

사망
↓

IsAiming = false
 

처럼 언제든지 원하는 상태로 변경할 수 있으며, 다른 기능에서도 현재 조준 중인지 쉽게 확인할 수 있다.

이를 통해 게임에서는 단순히 동작을 반복하는 것보다 현재 상태(State)를 변수로 관리하는 것이 훨씬 확장성과 유지보수에 유리하다는 점을 이해했다.

IA_Aim

 

후기

오늘은 단순히 강의를 따라 구현하는 것보다 "왜 이렇게 구현하는가"를 많이 고민한 시간이었다. 특히 Get Actor Forward Vector와 Get Control Rotation의 차이를 비교하면서 FPS와 TPS의 이동 방식이 서로 다르다는 점을 이해할 수 있었고, 프로젝트 구조에 따라 적절한 방법을 선택해야 한다는 것을 알게 되었다.

 

또한, 조준 기능을 구현하면서 처음에는 FlipFlop으로도 충분하다고 생각했지만, 실제 게임에서는 사망, 리스폰, 무기 교체처럼 다양한 상황이 발생하기 때문에 현재 상태를 Boolean 변수로 관리하는 것이 훨씬 중요하다는 점을 배웠다. 앞으로도 단순히 기능을 구현하는 것에 그치지 않고, 왜 이러한 구조를 사용하는지를 함께 생각하며 학습하는 습관을 계속 이어가야겠다고 느꼈다.

 

 

II. C언어 세션 (2회차)

개요

오늘은 C 언어의 기본 문법 중 연산자, 조건문, 반복문을 학습하였다. 단순히 문법을 익히는 것에 그치지 않고, 프로그램의 실행 흐름을 어떻게 제어하는지 이해하는 데 초점을 맞추었다. 

 

학습 내용

1) 연산자 (Operator)

연산자는 값을 계산하거나 비교하는 기호

예를 들어

int a = 10;
int b = 5;

int c = a + b;
 

여기서

  • + → 연산자
  • a, b → 피연산자

① 산술 연산자

숫자를 계산할 때 사용한다.

+ 더하기
- 빼기
* 곱하기
/ 나누기
% 나머지

 

② 복합 대입 연산자

기존 값에 계산 결과를 다시 저장한다.

a += 5;

a = a + 5;
 

와 동일하다.

 

③ 증감 연산자

i++;

i = i + 1;
 
i--;

i = i - 1;
 

 

④ 비교 연산자

여러 조건을 조합한다.

&&
 

AND

둘 다 참이어야 한다.

||
 

OR

하나만 참이어도 된다.

!
 

NOT

참과 거짓을 반대로 만든다.

 

⑤ 형변환(Casting)

자료형을 다른 자료형으로 바꾸는 것이다.

예를 들어

(int)3.8

3
 

소수점이 버려진다.

 

⑥ 삼항 연산자

간단한 if문을 한 줄로 표현한다.

score >= 60 ? "합격" : "불합격";
 

의미는

if(score >= 60)
{
    "합격";
}
else
{
    "불합격";
}
 

와 같다.

 

2) 조건문

조건에 따라 실행 내용을 바꾸는 문법이다.

① if

조건이 참일 때만 실행한다.

if(Health <= 0)
{
    printf("Game Over");
}
 
② if-else

참과 거짓을 모두 처리한다.

if(Ammo > 0)
{
    Fire();
}
else
{
    Reload();
}

 

③ else if

조건이 여러 개인 경우 사용한다.

if(score >= 90)
{
printf("A");
}

else if(score >= 80)
{
printf("B");
}

else if(score >= 70)
{
printf("C");
}

else
{
printf("F");
}

 

④ 중첩 if

if 안에 또 if를 넣는 구조이다.

if(HasKey)
{
    if(IsDoorLocked)
    {
        OpenDoor();
    }
}
 
⑤ switch-case

값에 따라 실행을 나눈다.

switch(WeaponType)
{
case 0:
    Knife();
    break;

case 1:
    Gun();
    break;
}
Intentional-Fallthrough를 사용할 수도 있다. (일부러 case문 안에 break문을 넣지 않는다. -> 다음 case 문도 실행된다.)
 
3) 반복문

같은 작업을 여러 번 실행한다.

① while

조건이 참인 동안 반복한다.

int i = 1;
	while (i < 5)
	{
		printf("%d ", i);
		++i;
	}

 

② for

반복 횟수가 정해져 있을 때 가장 많이 사용한다.

for(int i=0; i<10; i++) {printf("%d\n", i);}

0
1
2
3
...
9

 

③ do-while

먼저 한 번 실행한 후 조건을 검사한다.

do
{

} while(condition);

즉,

최소 한 번은 실행된다.

 

④ 무한 반복문

while (1)
{
...
}

for(i = 1; ; ++i)
{
...
}

 

⑤ break, continue

break는 반복문을 즉시 종료한다.

continue는 현재 반복만 건너뛰고, 다음 반복으로 넘어간다.

int i = 0;
	while (1)
	{
		if (i % 2 == 1)
		{
			++i;
			continue;
		}
		if (5 <= i)
		{
			break;
		}
		printf("%d ", i);
		++i;
	}

 

⑥ 이중 반복문

반복문 안에 반복문을 넣는다.

for(...)
{
    for(...)
    {

    }
}
 

주로

  • 2차원 배열
  • 게임 맵
  • 체스판
  • 타일 생성

등에서 많이 사용된다.

 

후기

오늘 학습한 내용은 대부분 언리얼 엔진 블루프린트에서 이미 사용해 본 개념들이라 비교적 이해하기 쉬웠다. Branch 노드가 if문에 해당하고, For Loop와 While Loop 역시 C 언어의 반복문과 동일한 개념이라는 점을 확인하면서 블루프린트와 C 언어가 서로 다른 것이 아니라 같은 로직을 다른 방식으로 표현하는 것이라는 사실을 느꼈다.

 

특히, 조건문과 반복문은 앞으로 게임 로직을 구현할 때 가장 많이 사용될 문법인 만큼, 문법 자체를 암기하기보다 언제 어떤 상황에서 사용하는지를 이해하는 것이 중요하다고 생각했다. 앞으로 C 언어를 학습할 때도 블루프린트에서 구현했던 기능들을 함께 떠올리며 공부하면 훨씬 자연스럽게 C++로 이어질 것이라는 자신감이 생겼다.

'언리얼 엔진 > TIL' 카테고리의 다른 글

TIL - 본캠프 4일차  (0) 2026.07.01
TIL - 본캠프 3일차  (0) 2026.06.30
TIL - 본캠프 1일차  (0) 2026.06.26
TIL - 베이스캠프 12일차  (0) 2026.06.24
TIL - 베이스캠프 11일차  (0) 2026.06.22