TIL
07.23 TIL
2026. 7. 23. 20:53

일정표

시간 할 일 비고
08:30~10:00 코드카타  
10:00~13:00 팀프로젝트  
14:00~18:00 팀프로젝트  
19:00~21:00 팀프로젝트 마무리  
21:00~22:00 운동  
22:00~23:30 개인 프로젝트  


*오늘의 코드카타*

 

문제. 둘만의 암호

더보기

두 문자열 s와 skip, 그리고 자연수 index가 주어질 때, 다음 규칙에 따라 문자열을 만들려 합니다. 암호의 규칙은 다음과 같습니다.

 

문자열 s의 각 알파벳을 index만큼 뒤의 알파벳으로 바꿔줍니다.

index만큼의 뒤의 알파벳이 z를 넘어갈 경우 다시 a로 돌아갑니다.

skip에 있는 알파벳은 제외하고 건너뜁니다.

예를 들어 s = "aukks", skip = "wbqd", index = 5일 때, a에서 5만큼 뒤에 있는 알파벳은 f지만 [b, c, d, e, f]에서 'b'와 'd'는 skip에 포함되므로 세지 않습니다. 따라서 'b', 'd'를 제외하고 'a'에서 5만큼 뒤에 있는 알파벳은 [c, e, f, g, h] 순서에 의해 'h'가 됩니다. 나머지 "ukks" 또한 위 규칙대로 바꾸면 "appy"가 되며 결과는 "happy"가 됩니다.

두 문자열 s와 skip, 그리고 자연수 index가 매개변수로 주어질 때 위 규칙대로 s를 변환한 결과를 return하도록 solution 함수를 완성해주세요

#include <string>
#include <vector>

using namespace std;

string solution(string s, string skip, int index) {
    string answer = "";

    string valid_alphabet = "";
    for (char c = 'a'; c <= 'z'; ++c) {
        if (skip.find(c) == string::npos) {
            valid_alphabet += c;
        }
    }

    for (char c : s) {
        int pos = valid_alphabet.find(c);

        int next_pos = (pos + index) % valid_alphabet.size();
        
        answer += valid_alphabet[next_pos];
    }
    
    return answer;
}

*TA*

라이팅 & 머티리얼(PBR) 기초

1. 라이팅의 역할과 연출 기법

1.1 라이팅의 6가지 핵심 역할

  1. 장면 명암 형성: 3D 공간을 시각적으로 인지할 수 있도록 밝히는 기본 기능.
  2. 형태 표출: 오브젝트의 굴곡, 텍스처 디테일, 볼륨감을 드러냄.
  3. 공간의 깊이와 위치 관계: 빛과 그림자의 대비를 통해 오브젝트 간의 전후 거리감 생성.
  4. 분위기(Mood) 연출: 색상과 대비를 활용해 서사적/감정적 분위기 조성.
  5. 플레이어 시선 유도 (Guiding): 시각적 본능(밝은 곳을 먼저 관찰함)을 이용해 이동 경로 안내.
  6. 상태 및 가이드 강조: 위험 지역(붉은 조명), 보상/목표 지점(강한 스팟 조명) 등을 피드백.
  7. 시간대 및 장소감: 태양 각도, 색온도, 환경광을 통해 계절, 시간(낮/밤), 장소(실내/실외) 표현.

1.2 디자인 이론과 라이팅

  • 대비(Contrast): 밝은 영역은 가시성이 높고, 어두운 영역은 위협/고립/숨겨진 요소의 분위기를 형성.
  • 그림자의 강도: 강하고 날카로운 그림자는 강렬한 주광원이나 긴장감을, 부드러운 그림자는 확산광이나 편안한 공간감을 부여.

1.3 3-Point Lighting & 인물 연출

피사체를 입체적으로 표현하기 위한 인물 조명 설정 기법입니다.

  • Key Light (주광원):
    • 장면에서 가장 강한 메인 조명.
    • 보통 카메라 기준 대각선 상단(45도 위치)에 배치하여 대상의 기본 구조와 양감 형성.
  • Fill Light (보조광원):
    • Key Light로 인해 생기는 강한 그림자(어두운 부분)를 완화하기 위한 부드러운(Soft) 조명.
    • 그림자가 새로 생기지 않도록 주광원보다 훨씬 약한 세기로 세팅.
  • Rim Light (윤곽광 / Back Light):
    • 피사체의 뒤쪽 대각선에서 비추어 머리카락이나 어깨의 윤곽선(Rim)을 밝힘.
    • 피사체가 배경과 묻히지 않고 분리되어 보이도록 만듦.
  • Rembrandt Lighting (렘브란트 라이팅):
    • 화가 렘브란트의 초상화 스타일에서 유래.
    • Key Light의 위치를 조절하여 빛을 받는 반대쪽 뺨에 삼각형 모양의 빛 상이 생기게 하는 기법.
    • 얼굴의 윤곽과 입체감을 극대화함.

1.4 Normal과 Light Direction ($N \cdot L$)

빛과 표면의 각도에 따른 밝기 계산의 기본 원리입니다.

  • Normal ($N$): 표면이 바라보는 정면 방향의 단위 벡터.
  • Light Direction ($L$): 표면 위치에서 광원을 향하는 단위 벡터.
  • 두 벡터의 내적값 $N \cdot L = \cos(\theta)$을 통해 빛을 직면할 때($N \cdot L = 1$) 가장 밝고, 스쳐 지나갈 때($N \cdot L = 0$) 어두워지는 램버트(Lambert) 명암이 결정됩니다.

<추가 : 빛의 방향과 명암 구성 요소>

1. 빛의 방향과 명암 구성 요소

3D 공간이나 미술에서 형태감을 만들 때, 빛은 표면에서 다양한 단계의 명암 영역을 형성합니다.

[ Direct Light (직사광) ]
                             │
                             ▼
  (카메라 방향) ──> [ Highlight (Specular) ]
                             │
                     [ Halftone (Midtone) ]
                             │
                     ==================  <-- Terminator (명암 경계선)
                             │
                     [ Core Shadow (핵심 그림자) ]  <-- 가장 짙은 음영
                             │
                     [ Bounce Light (반사광) ]      <-- 주변에서 들어오는 간접광
                             │
                     ==================
                  [ Occlusion Shadow (차폐 그림자) ] <-- 틈새/접촉부
                  [ Cast Shadow (투사 그림자) ]     <-- 타 표면에 형성

1.1 라이팅 방향

  • 전면 라이팅 (Front Lighting):
    • 카메라(관찰자) 시선과 거의 같은 방향에서 비추는 조명입니다.
    • 그림자가 피사체 뒤로 숨어 입체감이나 디테일은 납작(Flat)해지지만, 피사체의 고유 색상과 형태가 명확하게 드러납니다.
  • 측면 라이팅 (Side Lighting):
    • 카메라 기준 $90^\circ$ 측면에서 비추는 조명입니다.
    • 밝은 면과 어두운 면이 절반으로 나뉘며, 표면의 질감(Texture), 굴곡, 입체감이 극대화되고 드라마틱한 분위기를 만듭니다.

1.2 명암의 세부 구성 요소

  • Direct Light (직사광):
    • 광원에서 출발해 다른 표면에 반사되지 않고 피사체에 직접 도달하는 1차 빛입니다.
  • Highlight / Specular (하이라이트):
    • 직사광이 표면에 반사되어 카메라/눈으로 직접 들어오는 가장 밝은 정반사 포인트입니다. 표면의 거칠기(Roughness)에 따라 크기와 선명도가 달라집니다.
  • Halftone / Shading / Midtone (중간톤 / 반음영):
    • 직사광을 비스듬히 받는 영역으로, 밝은 영역에서 어두운 영역으로 자연스럽게 이행되는 중간 밝기 구간입니다 ($N \cdot L > 0$).
  • Terminator (명암 경계선):
    • 빛이 더 이상 직사로 도달하지 못하는 지점($N \cdot L = 0$)으로, 밝은 영역(Lit)과 어두운 영역(Unlit)을 나누는 경계선입니다.
  • Core Shadow (핵심 그림자):
    • Terminator 바로 뒤쪽에 위치하며, 어두운 면 중에서 가장 짙은 그늘 영역입니다. 반사광(Bounce Light)이 아직 미치지 않아 빛이 가장 부족합니다.
  • Bounce Light / Indirect Light (반사광 / 간접광):
    • 직사광이 바닥이나 주변 벽면에 부딪힌 뒤 튕겨 나와, 오브젝트의 어두운 그림자 면을 은은하게 다시 밝혀주는 빛입니다.
  • Cast Shadow (투사 그림자):
    • 물체가 빛을 차단하여 다른 물체나 바닥 표면에 드리우는 그림자입니다. 광원과의 거리에 따라 중심부는 어둡고(Umbra), 외곽으로 갈수록 부드러워집니다(Penumbra).
  • Occlusion Shadow / Ambient Occlusion (차폐 그림자 / 접촉 그림자):
    • 물체와 물체가 완전히 접촉하는 면, 혹은 깊은 구석/틈새처럼 반사광조차 들어가지 못해 형성되는 아주 짙은 틈새 그림자입니다.

2. 언리얼 엔진 Occlusion Shadow 세팅 및 GPU 최적화

Occlusion Shadow는 씬의 오브젝트가 공중에 떠 있는 듯한 느낌(Floating phenomenon)을 없애고, 바닥이나 물체 사이에 무게감과 접촉감을 주는 핵심 요소입니다.

언리얼 엔진에서 제공하는 대표적인 Occlusion 기법들과 GPU 사용량(패스 비용) 기준 최적 세팅 방식을 정리했습니다.

2.1 주요 Occlusion 기법별 GPU 부하 비교

기법 연산 방식 GPU 비용 특징 및 용도
Material AO 텍스처 맵 (Ambient Occlusion 핀) 0 ms (비용 없음) 머티리얼 자체에 구워진 정적 틈새 음영. 동적 조명 반응 불가.
SSAO 화면 공간 픽셀 차폐 계산 약 0.2 ~ 0.5 ms 가장 기본적인 포스트 프로세스 AO. 연산이 가벼움.
GTAO Ground Truth Screen-Space AO 약 0.5 ~ 1.2 ms SSAO보다 훨씬 정확하고 물리적으로 타당한 음영 생성.
Contact Shadows 화면 공간 레이마칭 (Light 속성) 약 0.3 ~ 0.8 ms 디렉셔널 라이트 등에서 세밀한 접촉 그림자(손가락, 풀잎) 보완.
DFAO Mesh Distance Field 기반 약 0.8 ~ 1.5 ms 대규모 야외 씬에서 중/원거리 차폐 표현에 적합.
Lumen AO 루멘 글로벌 일루미네이션 내부 연산 약 1.5 ~ 3.5 ms+ UE5 기본 GI 연산에 완벽 통합된 고품질 AO.

 

2.2 목표 성능별 추천 Occlusion 세팅

1) 타깃: 고성능 / 최신 PC (UE5 Lumen 기반 / 60 FPS Target)

UE5에서 루멘을 사용하는 프로젝트라면 기본 GI가 Occlusion을 포함하므로, 미세한 접촉부 그림자만 레이마칭으로 보완하는 것이 가장 가성비가 좋습니다.

  • Post Process Volume 세팅:
    • Ambient Occlusion: 루멘 GI를 사용 중이라면 SSAO는 Intensity 0으로 끄거나, GTAO를 가볍게 조합합니다.
  • Directional Light 세팅:
    • Contact Shadow Length: 0.02 ~ 0.05 설정 (값을 0.1 이상으로 높이면 스크린 스페이스 노이즈 및 GPU 연산량이 대폭 증가합니다).
    • Contact Shadow Length in World Space: 체크 (모니터 해상도에 영향받지 않고 일정 깊이 유지).

2) 타깃: 중급 PC / 타협형 씬 (Lumen 미사용 / 60~120 FPS Target)

루멘 대신 베이크 라이팅(Lightmass)이나 Screen Space 방식을 사용하는 환경에서는 GTAO를 활성화하는 것이 비주얼 대비 GPU 비용 효율이 가장 높습니다.

  • Post Process Volume 세팅:
    • Method: GTAO (Ground Truth Ambient Occlusion) 선택.
    • Radius: 100 ~ 200 (세계 단위 cm 기준, 반지름이 너무 크면 GPU 탐색 비용 상승).
  • 콘솔 변수 (C++ / DefaultEngine.ini 최적화):
r.GTAO.Enable=1
r.GTAO.Quality=2          ; 3(Max) 대비 GPU 비용을 30% 절감하면서 품질 유지
r.GTAO.Downsample=1       ; 절반 해상도로 연산하여 GPU 부하 절반 이하로 감소

3) 타깃: 저사양 / 모바일 / VR / 프레임 최우선 (120+ FPS Target)

동적 스크린 스페이스 연산을 최소화하고 정적 텍스처 및 베이크 데이터를 활용해야 합니다.

  • Material 세팅:
    • 텍스처 팩킹(RGB) 시 AO 맵을 포함하여 머티리얼의 Ambient Occlusion 입력 핀에 연결.
  • Project Settings:
    • Allow Static Lighting: Enabled (Lightmass로 AO 사전 계산).
    • Post Process Volume의 SSAO/GTAO/Contact Shadow 모두 Disabled (Intensity = 0).

실무 최적화 요약 팁

  1. Contact Shadow Length 제한: Contact Shadow는 편리하지만 Length 값을 높이면 화면 전체 픽셀을 레이마칭하므로 GPU 연산량이 급증합니다. 0.02 내외의 미세한 값만 사용하여 발바닥과 지면이 만나는 부분만 잡아주는 것이 좋습니다.
  2. GTAO 다운샘플링 활용: GTAO의 품질을 원하지만 GPU 보틀넥이 생길 경우 r.GTAO.Downsample 1 설정을 사용하면 절반 해상도에서 AO를 계산한 뒤 업스케일링하므로 프레임을 대폭 확보할 수 있습니다.

 

2. Unreal Light Actor 종류 및 물리 수식

2.1 렌더링 방정식 (Rendering Equation)

모든 조명 계산의 기본이 되는 반사 수식입니다.

  • $L_o(P,V)$:$P$에서 시선 방향 $V$로 나가는 최종 반사 광량
  • $L_e(P,V)$:$P$ 자체에서 나오는 발광(Emissive)
  • $f_r(P,L,V)$: BRDF (양방향 반사도 분포 함수 - 표면 재질에 따른 빛 반사 특성)
  • $L_i(P,L)$: 광원에서 입사되는 빛의 양
  • $V_{\text{shadow}}(P,L)$: 그림자 차폐 여부 (0: 가려짐, 1: 도달함)
  • $\max(0, N \cdot L)$: 코사인 감쇠 법칙 (입사각에 따른 빛 수광량)

2.2 Directional Light (직사광)

광원이 무한히 먼 곳에 위치한다고 가정하여, 모든 빛의 입사 방향이 평행한 태양광/달빛 라이트입니다.

  • $E_{\perp}$: 광선에 수직인 표면이 받는 조도 (언리얼의 Lux 단위 입력값)
  • 특징: 거리에 따른 광량 감쇠가 없으며, 장면 전체에 평행한 그림자를 형성함.

2.3 Point Light (점광원)

한 점에서 모든 방향(360도)으로 빛을 방사하는 광원입니다 (예: 전구, 촛불).

  • $I_v$: 광도 (Candela / Lumen)
  • $d$: 광원과 표면 $P$ 사이의 거리
  • 특징: 거리가 멀어짐에 따라 역제곱 법칙($1/d^2$)으로 빛이 감쇠함.

2.4 Spot Light (스팟광)

한 점에서 특정 원뿔(Cone) 방향으로 제한된 빛을 쏘는 광원입니다 (예: 손전등, 무대 조명).

  • $\theta_{\text{inner}} / \theta_{\text{outer}}$: 내각(Inner Cone)과 외각(Outer Cone) 각도.
  • 특징: 내각 안쪽은 최대 밝기를 유지하고, 내각과 외각 사이 구간에서 Smoothstep 형태로 페이드아웃 감쇠함.

2.5 Rect Light (면광원)

사각형의 면적을 가지고 빛을 내뿜는 광원입니다 (예: 창문으로 들어오는 빛, 형광등, 모니터 스크린).

  • 특징: 점 광원과 달리 표면적($A$)을 적분 계산하므로, 면적감 있는 광원 연출 및 거리에 따라 자연스럽게 퍼지는 부드러운 그림자(Soft Shadow)를 생성함.

2.6 Sky Light (환경광 / Ambient Light)

하늘 및 주변 씬 전체 큐브맵(Cubemap) 데이터를 기반으로 상공 전 반구에서 들어오는 부드러운 확산광/반사광을 계산합니다.

  • $L_{\text{prefiltered}}$: Roughness($\alpha$) 수준별로 미리 필터링(Blurring)된 환경 Cubemap.
  • $A, B$: BRDF Look-Up Table (LUT)에서 사전 계산되어 룩업되는 Scale & Bias 값.
  • $F_0$: 표면의 수직 입사 반사율 (Fresnel Reflection at $0^\circ$).
  • 특징: 실시간 반사(Specular IBL) 및 음영 지역의 그늘진 스카이 컬러(Diffuse IBL)를 완벽하게 표현함.

3. 빛의 속성 (세기, 감쇠, 색온도)

3.1 Intensity & Attenuation Radius

  • Intensity (빛의 세기): 광원의 출력을 결정. 강도가 높을수록 하이라이트가 강해지고 대비(Contrast)가 뚜렷해짐.
  • Attenuation Radius (감쇠 반경): Point Light / Spot Light의 빛이 영향을 미치는 한계 거리.
    • 영향 범위 밖의 오브젝트는 조명 계산에서 제외되어 GPU 연산 성능 최적화에 중요한 역할을 함.

3.2 Light Color vs Base Color

  • 렌더링 시 최종 색상 $\approx$ Base Color $\times$ Light Color 연산이 일어납니다.
  • Red Base Color에 Red Light를 비추면 붉은색이 강조되지만, Blue Light를 비추면 상호 곱할 채널이 없어 검은색에 가깝게 어두워집니다.

3.3 색온도 (Color Temperature, Kelvin)

흑체가 열을 받았을 때 방출하는 빛의 색을 절대온도 Kelvin($K$) 단위로 나타낸 것입니다.

색온도(K) 색상 감정 및 적용 상황
2000 ~ 3000K 촛불/노란빛 (주황, 따뜻함) 안락함, 아늑함, 촛불, 회상 장면, 노을
4000 ~ 5000K 중성광 (밝은 흰색) 사실적 표현, 일반 형광등, 낮 시간 실내 조명
6000 ~ 7500K 푸른빛 (차가움) 새벽녘, 긴장감, 고립감, 병원/실험실 음침함
8000K 이상 청보라 계열 비현실적 공간, 사이버펑크, 공포, 외계 환경

4. Texture, Shader, Material, Material Instance의 개념 구분

4.1 개념적 비교

[ Texture ]  ---> (데이터 공급: Albedo, Normal 등)
                       │
[ Shader ]   ---> (GPU 연산 코드: HLSL)
                       │
                       ▼
[ Material ] ---> (Shader + Texture + Parameter 결합체)
                       │
                       ▼
[ Material Instance ] ---> (Material 셰이더 공유 + 파라미터 값 변경 변형체)
구분 주요 역할 엔진 및 GPU 동작 특성
Texture 표면 텍셀 정보(RGB, Alpha)를 담은 이미지 데이터 파일. GPU VRAM에 메모리로 로드되는 2D/3D 이미지 리소스.
Shader Vertex/Pixel 조명, 반사, 위치 변경 등을 계산하는 실제 HLSL 코드. GPU 코어에서 직접 실행되는 렌더링 연산 파일.
Material Texture, Parameter, HLSL Shader Graph 노드를 조합한 가공 리소스. 원본 셰이더 컴파일을 수행하며, 렌더링 규칙을 정의함.
Material Instance 원본 Material의 Shader 구조를 그대로 재활용하고, 값(Value)만 바꾼 변형체. 셰이더 재컴파일이 불필요하여 드로우콜(Draw Call) 및 메모리 성능 최적화에 필수적임.

 

4.2 C++ 데이터 구조 관점 예시

엔진 내부에서 머티리얼과 머티리얼 인스턴스가 어떻게 상속 및 오버라이딩 구조로 관리되는지 C++ 데이터로 표현한 구조입니다.

#include <iostream>
#include <string>
#include <unordered_map>

// 1. 마스터 머티리얼 데이터 (C++ 셰이더 연결 구조)
struct FMaterialData {
    std::string MaterialName;
    std::string ShaderHLSLPath; // 실제 GPU에서 구동될 HLSL 셰이더 파일 경로
    
    // 머티리얼 기본 파라미터 정의
    std::unordered_map<std::string, float> ScalarParameters;
    std::unordered_map<std::string, std::string> TextureParameters;
};

// 2. 머티리얼 인스턴스 데이터 (마스터 머티리얼을 참조하고 값만 재정의)
struct FMaterialInstanceData {
    std::string InstanceName;
    const FMaterialData* ParentMaterial; // 마스터 머티리얼 포인터 참조 (셰이더 코드 공유)

    // 인스턴스에서 오버라이드(덮어쓰기)된 파라미터 값
    std::unordered_map<std::string, float> OverriddenScalarParameters;
    std::unordered_map<std::string, std::string> OverriddenTextureParameters;

    // 파라미터 평가 함수 (인스턴스에 값이 없으면 부모 값 참조)
    float GetScalarParameter(const std::string& ParamName) const {
        auto it = OverriddenScalarParameters.find(ParamName);
        if (it != OverriddenScalarParameters.end()) {
            return it->second; // 오버라이드된 값 반환
        }
        // 부모 머티리얼의 기본값 반환
        return ParentMaterial->ScalarParameters.at(ParamName);
    }
};

 

5. PBR(Physically Based Rendering) 입력 파라미터 상세

PBR은 에너지 보존 법칙(Energy Conservation)을 기반으로, 물체에 입사된 빛의 합보다 반사/흡수되는 빛의 합이 클 수 없다는 물리 법칙을 따르는 렌더링 방식입니다.

5.1 Base Color (기본 색상)

표면의 고유 알베도(Reflectance) 색상입니다. 조명/그림자 정보가 포함되지 않은 pure 한 값이어야 합니다.

1) 비금속 (Dielectric) 베이스 컬러 수치

비금속은 단색 $RGB$ 스칼라 빛을 난반사(Diffuse)합니다.

머티리얼 베이스 컬러 강도 (sRGB / Linear)
숯 (Charcoal) 0.02
새 아스팔트 0.02
헌 아스팔트 0.08
맨땅 (Soil) 0.13
풀밭 (Grass) 0.21
모래사막 0.36
새 콘크리트 0.51
빙하 (Ice) 0.56
갓 내린 눈 (Fresh Snow) 0.81

2) 금속 (Conductor) 베이스 컬러 $F_0$ 수치

금속은 Diffuse 반사가 없으며(0), Base Color 값이 곧 수직 입사 반사율($F_0$ Specular Color)로 작동합니다.

머티리얼 베이스 컬러 RGB (Linear)
철 (Iron) (0.560, 0.570, 0.580)
은 (Silver) (0.972, 0.960, 0.915)
알루미늄 (Aluminum) (0.913, 0.921, 0.925)
금 (Gold) (1.000, 0.766, 0.336)
구리 (Copper) (0.955, 0.637, 0.538)
크롬 (Chromium) (0.550, 0.556, 0.554)
니켈 (Nickel) (0.660, 0.609, 0.526)
티타늄 (Titanium) (0.542, 0.497, 0.449)
백금 (Platinum) (0.672, 0.637, 0.585)

5.2 Roughness (거칠기)

  • 0.0 (매끄러움): 거울과 같이 날카롭고 선명한 반사 하이라이트를 형성함.
  • 1.0 (거침): 미세면(Microfacet)에 의해 빛이 사방으로 산란되어 흐릿하고 둔탁한 반사를 형성함.

5.3 Metallic (금속성)

  • 0.0 (비금속 - Dielectric): 플라스틱, 나무, 돌 등. Diffuse 반사가 일어나고 $F_0$ Specular 반사율은 기본값인 약 4%(0.04)로 고정됨.
  • 1.0 (금속 - Metallic): 전도체. Diffuse 반사가 전혀 없으며, Specular 반사에 Base Color의 색상이 입혀짐.

5.4 Normal (법선)

  • 픽셀 단위로 표면의 Normal 방향 벡터를 교체하여, 메시의 버텍스를 직접 수정하지 않고도 표면의 정교한 음영/입체 디테일을 만듦.

5.5 World Position Offset (WPO)

  • Vertex Shader 단계에서 메쉬의 버텍스 위치를 월드 스페이스 상에서 직접 이동시킵니다.
  • 바람에 흔들리는 나뭇잎, 파도치는 바수면, 캐릭터 축소/팽창 애니메이션 표현에 유용하게 쓰입니다.

5.6 Ambient Occlusion (AO)

  • 오브젝트의 구석진 틈새나 접합부에서 환경광(Ambient Light)이 차단되어 자연스럽게 어두워지는 자체 그림자 효과입니다.

6. 주요 머티리얼 노드 연산 및 활용

노드 연산 동작 수학식 주요 실무 활용 예시
Add $A + B$ 빛의 밝기를 가산하거나, UV 좌표에 오프셋(Offset)을 주어 텍스처를 이동시킬 때 사용.
Multiply $A \times B$ 텍스처에 Tint 색상을 곱하거나, 마스크(Mask) 채널을 적용하여 렌더링 영역을 제한할 때 사용.
Divide $A \div B$ UV 타일링 크기를 조절하거나 특정 파라미터 스케일을 축소할 때 활용.
Lerp (Linear Interpolate) $A \times (1 - Alpha) + B \times Alpha$ 세 번째 입력값($Alpha$)을 마스크로 사용하여 두 가가지 텍스처나 색상을 부드럽게 블렌딩함.
Power $Base^{Exp}$ 대조(Contrast) 조절 효과. 매우 밝은 영역은 유지하면서 어두운 영역을 급격히 어둡게 만들어 마스크의 선명도를 조절할 때 사용.

 


*라이라 파먹기 Chapter 1. DefaultEngine.ini*

DefaultEngine은 시스템 설계도 그 자체이다. C++ 코드에서 매니저나 콜리전 채널을 작성했더라도 이 파일에 등록되지 않으면 엔진은 기본 엔진 클래스로 동작하게 된다. DefaultEngine의 핵심 항목 6가지 그룹에 대해 알아보자.

 

1. [/Script/Engine.Engine]

[/Script/Engine.Engine]
GameEngine=/Script/LyraGame.LyraGameEngine
UnrealEdEngine=/Script/LyraEditor.LyraEditorEngine
GameViewportClientClassName=/Script/LyraGame.LyraGameViewportClient
AssetManagerClassName=/Script/LyraGame.LyraAssetManager
WorldSettingsClassName=/Script/LyraGame.LyraWorldSettings
LocalPlayerClassName=/Script/LyraGame.LyraLocalPlayer
GameUserSettingsClassName=/Script/LyraGame.LyraSettingsLocal
NearClipPlane=3.000000

엔진 초기화 단계에서 기본 언리얼 엔진 클래스 대신 전용 C++ 커스텀 클래스를 엔진의 기본 모듈로 Cache하는 블록이다.

 

 

AssetManagerClassName (ULyraAssetManager): 라이라의 핵심. 엔진 기본 에셋 매니저 대신 라이라 커스텀 에셋 매니저를 등록하여, 게임 실행 도중 무기/스킨 등의 에셋을 비동기 지연 로딩(Async Loading)할 수 있게 만든다.

 

WorldSettingsClassName (ALyraWorldSettings): 각 맵(Level)의 월드 세팅을 제어한다. 기획자가 에디터 월드 세팅 패널에서 Default Experience(기본 경험 데이터)를 지정할 수 있게 해주는 C++ 통로이다.

 

LocalPlayerClassName & GameUserSettingsClassName: 유저의 키 바인딩, 그래픽 세팅, 오디오 세팅을 로컬 파일로 저장하고 불러오는 라이라 전용 로컬 플레이어 시스템을 등록한다.

 

NearClipPlane=3.000000: 카메라가 캐릭터나 벽에 아주 가까이 붙었을 때 화면이 뚫려 보이는 현상(Clipping)을 방지하기 위해 근접 절단면을 3 unit으로 좁혀 두었다.

 

 

 

2. [/Script/Engine.CollisionProfile]

DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Lyra_TraceChannel_Interaction")
DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Lyra_TraceChannel_Weapon")
DefaultChannelResponses=(Channel=ECC_GameTraceChannel3,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Lyra_TraceChannel_Weapon_Capsule")
DefaultChannelResponses=(Channel=ECC_GameTraceChannel4,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Lyra_TraceChannel_Weapon_Multi")
DefaultChannelResponses=(Channel=ECC_GameTraceChannel5,DefaultResponse=ECR_Ignore,bTraceType=True,bStaticObject=False,Name="Lyra_TraceChannel_AimAssist")

총기 사격, 에임 보정, 상호작용 판정이 정확히 동작할 수 있도록 하는 세팅.

 

Lyra_TraceChannel_Interaction : 아이템 상자, 문, 장치 등 E키 상호작용 타겟을 감지하는 전용 레이캐스트 채널

 

Lyra_TraceChannel_Weapon : 단발 총기 사격 시 스켈레탈 메시(본 단위) 정밀 타격 판정 채널

Lyra_TraceChannel_Weapon_Capsule : 메쉬 정밀 판정 전, 1차적으로 캡슐 콜리전에 빠르게 부딪혔는지 검사하는 고성능 최적화 채널

Lyra_TraceChannel_Weapon_Multi : 샷건이나 궤적 관통 무기처럼 다중 대상을 관통/타격할 때 사용되는 채널

Lyra_TraceChannel_AimAssist : 콘솔/패드 조작 시 적 캐릭터 주변에 감지용 영역을 두어 에임 보정을 적용하는 채널

 

 

3. [/Script/EngineSettings.GameMapsSettings]

[/Script/EngineSettings.GameMapsSettings]
GlobalDefaultGameMode=/Game/B_LyraGameMode.B_LyraGameMode_C
GameInstanceClass=/Game/B_LyraGameInstance.B_LyraGameInstance_C
GameDefaultMap=/Game/System/FrontEnd/Maps/L_LyraFrontEnd.L_LyraFrontEnd
EditorStartupMap=/Game/System/DefaultEditorMap/L_DefaultEditorOverview.L_DefaultEditorOverview

게임이 실행되거나 에디터를 열 때 가장 먼저 로드될 로비 맵과 기본 GameMode/GameInstance를 지정한다.

 

 

GameDefaultMap: 빌드된 패키지 게임(.exe)을 실행했을 때 가장 먼저 뜨는 대기실/메인 메뉴 맵 (L_LyraFrontEnd).

 

GlobalDefaultGameMode: 맵에 별도의 GameMode가 지정되어 있지 않을 때 작동할 기본 C++ 기반 블루프린트 GameMode.

 

 

 

4. [/Script/Engine.RendererSettings]

r.ReflectionMethod=1                   ; Lumen 반사 활성화
r.DynamicGlobalIlluminationMethod=1     ; Lumen 글로벌 일루미네이션 활성화
r.Shadow.Virtual.Enable=1              ; 버추얼 섀도 매핑(VSM) 활성화
r.RayTracing=True                      ; 하드웨어 레이 트레이싱 사용
r.Substrate=1                          ; UE5.2+ 차세대 머티리얼 시스템 Substrate 활성화

라이라가 사용하는 렌더링 설정 세트.

 

r.Substrate=1: 언리얼 엔진 5의 차세대 셰이딩/머티리얼 프레임워크인 Substrate(구 Strata)를 프로젝트 전역에 켜둔 설정. 복잡한 다층 머티리얼(금속, 유리, 피부 등)의 피직스 기반 렌더링을 매우 정교하게 처리한다.

 

 

5. [ 멀티플레이어 대역폭 & Iris 리플리케이션 ]

[/Script/Engine.Player]
ConfiguredInternetSpeed=200000         ; 플레이어당 초당 대역폭 (약 200KB/s)

[/Script/OnlineSubsystemUtils.IpNetDriver]
MaxClientRate=200000

[/Script/IrisCore.ReplicationStateDescriptorConfig]
+SupportsStructNetSerializerList=(StructName=LyraGameplayAbilityTargetData_SingleTargetHit)

멀티플레이어 환경에서 네트워크 병목 현상을 막기 위한 대역폭 및 차세대 네트워크 시스템 설정.

 

 

MaxClientRate=200000: 기본 언리얼 네트워크 속도 설정(보통 10,000~15,000)보다 훨씬 높은 200KB/s의 대역폭을 확보하여, 수십 명의 플레이어가 동시에 사격하고 스킬을 써도 네트워크 동기화가 끊기지 않도록 대용량 통신망을 뚫어둔 것을 확인할 수 있다.

 

IrisCore: 언리얼 엔진 5의 차세대 고성능 멀티플레이어 리플리케이션 시스템인 Iris를 사용할 수 있도록 타겟 데이터 구조체.(LyraGameplayAbilityTargetData_SingleTargetHit)를 직렬화(Serialization) 등록해 둔 흔적이다.

 

 

 

6. [ SignificanceManager & PhysicsSurfaces ]

[/Script/SignificanceManager.SignificanceManager]
SignificanceManagerClassName=/Script/LyraGame.LyraSignificanceManager

[/Script/Engine.PhysicsSettings]
+PhysicalSurfaces=(Type=SurfaceType1,Name="Character")
+PhysicalSurfaces=(Type=SurfaceType2,Name="Concrete")
+PhysicalSurfaces=(Type=SurfaceType3,Name="Glass")

 

LyraSignificanceManager: 화면 멀리 있는 적 NPC나 이펙트의 틱(Tick) 주기를 자동으로 줄여 프레임을 확보하는 '중요도(Significance) 평가 매니저'를 커스텀 클래스로 등록해 둔 것이다.

 

PhysicalSurfaces: 총알이 어디에 맞아 튕겼는지에 따라 다른 이펙트/사운드(피 튀김, 콘크리트 파편, 유리 깨짐 등)를 출력할 수 있도록 C++ 상에서 판정할 피지컬 서피스 타입을 선언해 둔 것이다.

 

 

 

...===...

 

<DefaultEngine.ini 체크리스트>

 

"C++ 매니저 클래스를 새로 만들었는데 엔진이 안 읽어줄 때"

AssetManagerClassName, WorldSettingsClassName에 작성한 커스텀 클래스가 등록되어 있는지 확인하기.

 

"총알 사격이나 E키 상호작용 전용 라인트레이스 채널을 만들고 싶을 때"

DefaultChannelResponses 섹션에 ECC_GameTraceChannel 구문을 추가하기.

 

"멀티플레이 시 네트워크 변수 동기화나 RPC가 자꾸 밀리거나 씹힐 때"

MaxClientRate 대역폭 수치 및 net.MaxRPCPerNetUpdate CVar 설정을 수정하기.

 

"총탄이 벽이나 캐릭터에 맞았을 때 재질별 물리 이펙트를 다르게 주고 싶을 때"

PhysicalSurfaces 항목에 태그를 등록하기.

 

 

 

...===...


*라이라 파먹기 Chapter 2. DefaultGame.ini*

DefaultEngine.ini가 엔진 시스템과 물리/콜리전의 '심장부'였다면, DefaultGame.ini는 게임플레이 규칙, GAS(Gameplay Ability System) 전역 제어, 에셋 스캔 규칙, UI 프레임워크, 패키징 쿠킹 설정이 모여 있는 '게임플레이 총괄 본부'이다.

 

1. [ /Script/GameplayAbilities.AbilitySystemGlobals ]

[/Script/GameplayAbilities.AbilitySystemGlobals]
AbilitySystemGlobalsClassName=/Script/LyraGame.LyraAbilitySystemGlobals
GlobalGameplayCueManagerClass=/Script/LyraGame.LyraGameplayCueManager
+GameplayCueNotifyPaths=/Game/GameplayCueNotifies
+GameplayCueNotifyPaths=/Game/GameplayCues
ActivateFailCooldownTag=(TagName="Ability.ActivateFail.Cooldown")
ActivateFailCostTag=(TagName="Ability.ActivateFail.Cost")
MinimalReplicationTagCountBits=5

GAS(Gameplay Ability System) 전역 설정 파트. 모든 스킬, 어트리뷰트(스탯), 데미지, 상태 이상 판정을 총괄하는 전역 세팅이다.

 

AbilitySystemGlobalsClassName: 언리얼 기본 GAS 글러벌 클래스 대신 ULyraAbilitySystemGlobals를 등록하여 타겟 데이터 및 어트리뷰트 초기화 로직을 커스텀한다.

 

GlobalGameplayCueManagerClass & GameplayCueNotifyPaths: 이펙트/사운드/애니메이션 연출을 담당하는 GameplayCue들을 어느 폴더 경로에서 자동으로 스캔할지 지정한다.

 

ActivateFail...Tag: 마나 부족(Cost), 쿨타임 중(Cooldown), 스턴 상태(TagsBlocked) 등으로 스킬 발동이 실패했을 때 UI나 C++ 코드에 전달할 태그를 등록한다.

 

MinimalReplicationTagCountBits=5: 네트워크 리플리케이션 시 태그 개수를 몇 비트 단위로 직렬화(Serialization)할지 정하는 네트워크 최적화 수치이다.

 

 

2. [/Script/Engine.AssetManagerSettings]

[/Script/Engine.AssetManagerSettings]
+PrimaryAssetTypesToScan=(PrimaryAssetType="LyraExperienceDefinition",AssetBaseClass="/Script/LyraGame.LyraExperienceDefinition",bHasBlueprintClasses=True,bIsEditorOnly=False,Directories=((Path="/Game/System/Experiences")),Rules=(CookRule=AlwaysCook))
+PrimaryAssetTypesToScan=(PrimaryAssetType="GameFeatureData",AssetBaseClass="/Script/GameFeatures.GameFeatureData",bHasBlueprintClasses=False,bIsEditorOnly=False,Directories=((Path="/Game/Unused")),Rules=(CookRule=AlwaysCook))

에셋 매니저 & 프라이머리 에셋 스캔파트. 하드코딩을 배제하고 데이터 주도 설계(Data-Driven Design)를 완성할 수 있게 만들어주는 일등 공신이다. 엔진이 실행될 때 어떤 데이터 에셋들을 자동으로 스캔해서 메모리 레지스트리에 등록할지 지정한다.

 

PrimaryAssetTypesToScan: 특정 폴더 경로에 있는 데이터 에셋(예: Experience, GameFeature, UserFacingExperience)을 엔진이 켜질 때 'Primary Asset'으로 자동 등록한다.

 

CookRule=AlwaysCook: 패키징 시 사용되지 않는 것처럼 보이는 에셋이라도 런타임에 동적으로 로드해야 하므로 빌드 파일(.pak)에 반드시 포함시키도록 강제한다.

 

 

3. [ /Script/GameFeatures.GameFeaturesSubsystemSettings ]

[/Script/GameFeatures.GameFeaturesSubsystemSettings]
GameFeaturesManagerClassName=/Script/LyraGame.LyraGameFeaturePolicy

모듈형 GameFeatures 정책파트. 

 

LyraGameFeaturePolicy: 라이라의 핵심 아키텍처인 GameFeatures 플러그인을 주입/해제하는 관제 정책. 특정 맵(Experience)에 진입할 때 플러그인 메모리 로딩, 훅(Hook) 연결, 컴포넌트 자동 부착(Action) 순서를 관리한다.

 

 

4. [ /Script/CommonUI.CommonUISettings ]

[/Script/LyraGame.LyraUIManagerSubsystem]
DefaultUIPolicyClass=/Game/UI/B_LyraUIPolicy.B_LyraUIPolicy_C

[/Script/CommonInput.CommonInputSettings]
bEnableInputMethodThrashingProtection=True
InputMethodThrashingLimit=30

[/Script/CommonLoadingScreen.CommonLoadingScreenSettings]
LoadingScreenWidget=/Game/UI/Foundation/LoadingScreen/W_LoadingScreen_Host.W_LoadingScreen_Host_C

크로스플랫폼 지원 및 고성능 UI 프레임워크인 CommonUI 설정 모음. 

 

 

LyraUIManagerSubsystem: 게임 상의 레이어(Layer) 기반 UI(HUD, 팝업창, 대화창 등)를 스택 구조로 관리하는 UI 정책 클래스를 지정한다.

 

bEnableInputMethodThrashingProtection: 키보드/마우스 ↔ 패드/콘솔 입력을 빠르게 교체할 때 입력 방식이 미친 듯이 튀는 현상(Thrashing)을 방지하는 안전장치이다.

 

CommonLoadingScreenSettings: 맵과 맵 사이(마을 ↔ 던전)를 이동할 때 비동기 백그라운드 로딩 중 띄워줄 로딩 화면 위젯을 엔진 수준에서 등록해 둔다.

 

 

 

5. [ /Script/LyraGame.LyraAudioSettings ]

[/Script/LyraGame.LyraAudioSettings]
OverallVolumeControlBus=/Game/Audio/Modulation/ControlBuses/CB_Main.CB_Main
MusicVolumeControlBus=/Game/Audio/Modulation/ControlBuses/CB_Music.CB_Music
SoundFXVolumeControlBus=/Game/Audio/Modulation/ControlBuses/CB_SFX.CB_SFX

[/Script/LyraGame.LyraContextEffectsSettings]
SurfaceTypeToContextMap=((SurfaceType1, (TagName="SurfaceType.Character")),(SurfaceType2, (TagName="SurfaceType.Concrete")))

 

사운드 모듈레이션 & 재질 피격 매핑 등을 설정하는 파트.

 

AudioSettings (ControlBus): UI 옵션 창에서 전체 음량, BGM, SFX, 보이스 음량을 조절할 때 C++ 사운드 바인딩 코드를 직접 짜지 않고, 오디오 모듈레이션 버스(Control Bus)를 통해 동적으로 연결해 주는 설정이다.

 

LyraContextEffectsSettings: DefaultEngine.ini에 선언했던 물리 서피스(SurfaceType1)를 인게임 이펙트 태그(SurfaceType.Character)로 1:1 매핑해 주는 다리 역할을 한다.

 

 

 

6. [ /Script/UnrealEd.ProjectPackagingSettings ]

[/Script/UnrealEd.ProjectPackagingSettings]
PackageCompressionFormat=Oodle
PackageCompressionMethod=Kraken
bGenerateChunks=true
+MapsToCook=(FilePath="/Game/System/FrontEnd/Maps/L_LyraFrontEnd")
+CulturesToStage=en
+CulturesToStage=ko

프로젝트 패키징 & 에셋 쿠킹파트. 최종 게임을 패키징(.exe 빌드)할 때 에셋을 어떻게 압축하고 파일화할지 결정한다.

 

 

Kraken / Oodle: 언리얼 엔진 5의 최신 고성능 압축 알고리즘을 사용하여 게임 패키지 용량을 획기적으로 줄이고 로딩 속도를 높인다.

 

bGenerateChunks=true: 에셋들을 쪼개진 청크(Chunk) 단위로 묶어 패키징하므로, 향후 패치나 DLC 적용, 혹은 비동기 로딩을 유연하게 처리할 수있다.

 

CulturesToStage: 다국어 지원을 위해 포함시킬 언어 팩(한국어 ko, 영어 en 등)을 선언한다.

 

 

...===...

 

<DefaultGame.ini 체크리스트>

구 분 프로젝트 적용 핵심 포인트
AssetManager 스캔 용병 데이터, 장비 조합표, 주점 가구 버프, 대화 시나리오 데이터 에셋을 자동 스캔할 PrimaryAssetTypesToScan 항목 추가 등록
CommonUI & 로딩 화면 마을 ↔ 던전 이동 시 심리스 로딩 위젯 연결 및 탑다운 ↔ 3인칭 시점 스위칭 시 UI 포커스 레이어 통제
GAS 실패 태그 관리 오토배틀 및 WASD 스킬 사용 시 마나 부족, 쿨타임, 스턴 등의 이유로 스킬 실패 시 출력될 태그 세팅
오디오 모듈레이션 영지 경영(마을 BGM)과 던전 탐험(전투 BGM) 간의 자연스러운 오디오 컨트롤 버스 연동

 

 

...===...


*라이라 파먹기 Chapter 3. DefaultEditor.ini*

DefaultEngine.ini와 DefaultGame.ini가 런타임 게임의 뼈대와 시스템을 잡는 파일이었다면, DefaultEditor.ini는 개발진(C++ 프로그래머, 블루프린트 기획자, UI 디자이너)의 개발 생산성과 데이터 무결성을 보장하는 '에디터 관제 센터'이다.

 

라이라 프로젝트의 DefaultEditor.ini를 뜯어보면 에픽게임즈가 수십 명의 협업 환경에서 "기획자의 실수를 어떻게 시스템적으로 막는가", "CommonUI 시스템을 어떻게 강제하는가", "다국어 대화 텍스트를 어떻게 수집하는가"에 대한 노하우가 집약되어 있다.

 

1. [ /Script/UnrealEd.UnrealEdOptions  ]

[/Script/UnrealEd.UnrealEdOptions]
!NewAssetDefaultClasses=ClearArray
+NewAssetDefaultClasses=(ClassName="/Script/LyraGame.LyraCharacter", AssetClass="/Script/Engine.Blueprint")
+NewAssetDefaultClasses=(ClassName="/Script/LyraGame.LyraGameMode", AssetClass="/Script/Engine.Blueprint")
+NewAssetDefaultClasses=(ClassName="/Script/LyraGame.LyraGameplayAbility", AssetClass="/Script/Engine.Blueprint")
+NewAssetDefaultClasses=(ClassName="/Script/GameplayAbilities.GameplayEffect", AssetClass="/Script/Engine.Blueprint")
+NewAssetDefaultClasses=(ClassName="/Script/GameplayAbilities.GameplayCueNotify_Burst", AssetClass="/Script/Engine.Blueprint")

 

블루프린트 생성 시 C++ 베이스 클래스 우선 노출파트.

 

기획자나 아티스트가 에디터에서 [우클릭 후 블루프린트 생성]을 누를 때, 언리얼 기본 클래스(Character, Actor) 대신 프로젝트 전용 C++ 클래스를 최상단에 기본 노출하도록 강제한다.

 

 

설정의 의도: 팀원이 실수로 언리얼 기본 ACharacter나 AGameModeBase를 상속받아 블루프린트를 만드는 불상사를 차단한다.

 

프로젝트 적용: DGA용 커스텀 클래스(DgaCharacter, DgaGameplayAbility, DgaMercenaryDefinition 등)를 이 목록에 등록해 두면, 블루프린트를 만들 때 항상 DGA 전용 C++ 뼈대를 상속받게 만들어 아키텍처의 파편화를 방지할 수 있다.

 

 

 

2. [ /Script/UMGEditor.UMGEditorProjectSettings  ]

[/Script/UMGEditor.UMGEditorProjectSettings]
DefaultCompilerOptions=(bAllowBlueprintTick=True,bAllowBlueprintPaint=True,PropertyBindingRule=Prevent,Rules=)
bShowWidgetsFromEngineContent=False
bShowWidgetsFromDeveloperContent=True
+WidgetClassesToHide=/Script/UMG.WidgetSwitcher
+WidgetClassesToHide=/Script/UMG.TextBlock

CommonUI 강제 및 표준 UMG 위젯 숨김파트.

 

라이라는 CommonUI 프레임워크를 기반으로 구축되었다. 개발자가 구형 기본 UMG 위젯을 사용하는 것을 에디터 차원에서 아예 덮어버리고 숨기는 방식이다.

 

 

+WidgetClassesToHide: 기본 UMG의 TextBlock이나 WidgetSwitcher를 팔레트 창에서 숨김 처리한다. 대신 CommonUI 전용 위젯(CommonTextBlock, CommonAnimatedSwitcher)을 사용하도록 유도한다.

 

PropertyBindingRule=Prevent: UMG에서 성능 저하의 주범인 바인딩(Property Binding - 매 프레임 Tick으로 갱신하는 구식 방식) 기능을 에디터에서 아예 금지시킨다.

 

프로젝트 적용: 오토배틀러 HUD, 영지 경영 상점 UI, 하단 타이핑 대화 UI 등 수많은 UI가 오가는 프로젝트에서, UI 성능을 갉아먹는 매 프레임 바인딩을 차단하고 CommonUI 표준을 강제하는 매우 중요한 세팅이다.

 

 

 

3. [ DebugResolutions  ]

+DebugResolutions=(Width=3840,Height=2160,Description="",Color=...)
+DebugResolutions=(Width=3440,Height=1440,Description="",Color=...) ; 21:9 울트라 와이드
+DebugResolutions=(Width=2560,Height=1080,Description="",Color=...)

UI 해상도 및 화면비 사전 테스트 설정파트.

 

탑다운 쿼터뷰와 3인칭 WASD 조작을 넘나들 때, 다양한 모니터 해상도 및 화면비(울트라 와이드, QHD, 4K 등)에서 UI 레이아웃이 깨지지 않는지 UMG 디자이너 창에서 바로 테스트할 수 있게 해주는 해상도 프리셋 모음이다.

 

프로젝트 적용: 탑다운 쿼터뷰 모드에서 울트라 와이드(21:9) 해상도 적용 시 화면 양옆 양지 경영 UI나 던전 시야각(FOV)이 정성적으로 잡히는지 에디터 내에서 즉시 전환하며 검증할 수 있다.

 

 

4. [ /Script/Localization.LocalizationSettings  ]

+GameTargetsSettings=(Name="Game", ... GatherFromTextFiles=(IsEnabled=True,SearchDirectories=((Path="Source"),(Path="Config"),(Path="Plugins")), FileExtensions=((Pattern="h"),(Pattern="cpp"),(Pattern="ini"))), GatherFromPackages=(IsEnabled=True,IncludePathWildcards=((Pattern="Content/*"))), SupportedCulturesStatistics=((CultureName="en"),(CultureName="ko"), ...))

대화형 시나리오 & 다국어 텍스트 자동 수집파트.

 

프로젝트의 '대화형 시나리오''이원화 대화 UI(말풍선/타이핑 UI)' 구현에 있어 가장 핵심이 되는 다국어 지역화(Localization) 텍스트 수집 규칙이다.

설정의 의도: C++ 코드(FText), 블루프린트, .ini 파일, 에셋 파일 내에 존재하는 모든 인게임 텍스트(대화 스크립트, 아이템 설명, 스킬 이름)를 에디터의 대화 수집 툴(Localization Dashboard)이 지정된 폴더 경로에서 자동으로 긁어모을 수 있도록 파이프라인을 설정한다.

 

프로젝트 적용: 주점 몬스터 대화, 퀘스트 시나리오, 용병 상호작용 등 방대한 대화 텍스트가 데이터 에셋이나 C++에 들어갈 때, 텍스트가 누락되지 않고 한국어(ko), 영어(en) 등 타겟 언어 집합으로 자동 묶이게 만든다.

 

 

 

5. [ /Script/GameFeaturesEditor.GameFeaturesEditorSettings  ]

+PluginTemplates=(Path=..., Label="Game Feature (Content Only)", bIsEnabledByDefault=True)
+PluginTemplates=(Path=..., Label="Game Feature (with C++)", bIsEnabledByDefault=True)

Game Features 모듈형 플러그인 템플릿 활성화파트.

 

설정의 의도: 에디터에서 새로운 기능(예: 특정 던전 전용 시스템, 영지 경영 전용 모듈 등)을 추가하려 할 때, 메인 게임 코드를 건드리지 않고 새로운 GameFeature 플러그인으로 쉽게 생성할 수 있도록 에디터 템플릿을 기본 활성화해 둔다.

 

 

...===...

 

<DefaultEditor.ini 체크리스트>

구 분 프로젝트 적용 핵심 포인트
C++ 클래스 강제 블루프린트 생성 시 DgaCharacter, DgaGameplayAbility 등 DGA 전용 C++ 클래스를 기본 선택지로 노출
CommonUI & UI 성능 규제 기본 UMG TextBlock 숨김 및 레거시 Property Binding 차단으로 고성능 CommonUI 체계 통제
해상도 검증 환경 탑다운 쿼터뷰 전장 조망 시 울트라 와이드(21:9) 및 다양한 모니터 해상도 대응 UI 프리셋 세팅
대화/시나리오 Localization DGA의 대화형 시나리오 및 UI 텍스트(말풍선/타이핑) 자동 수집을 위한 Localization 파이프라인 개설

 

...===...


*라이라 파먹기 Chapter 4. DefaultGameplayTags.ini*

아키텍처의 혈관과 신경망 역할을 하는 DefaultGameplayTags.ini를 분석해보자.

라이라(Lyra)와 현대 언리얼 엔진 5 데이터 주도 설계(Data-Driven Design)의 핵심 철학은 "문자열(String)이나 하드코딩된 Enum을 쓰지 말고, 계층 구조를 가진 GameplayTag를 사용하라"다.

이 파일에 등록된 태그들은 단순한 이름표가 아니라 GAS 스킬 매핑, 입력 연결, CommonUI 레이어 통제, 글로벌 메시지 방송, 이펙트 재생의 기준점이 된다.

 

1. [ /Script/GameplayTags.GameplayTagsSettings  ]

[/Script/GameplayTags.GameplayTagsSettings]
ImportTagsFromConfig=True
WarnOnInvalidTags=True
FastReplication=True
+GameplayTagTableList=/Game/ContextEffects/DT_AnimEffectTags.DT_AnimEffectTags
NumBitsForContainerSize=6
NetIndexFirstBitSegment=16

태그 글로벌 환경 및 데이터 테이블 설정파트.

 

 

ImportTagsFromConfig=True: C++ 코드나 데이터 테이블(DataTable) 외에, 이 .ini 파일에 적힌 태그 목록을 프로젝트 실행 시 전역 태그 레지스트리에 자동 등록한다.

 

FastReplication=True: 네트워크 리플리케이션 시 문자열을 다 보낼 필요 없이 내부적인 고유 정수 Index로 변환하여 네트워크 대역폭을 비약적으로 아낀다.

 

GameplayTagTableList: Data Table 에셋 형태로 관리되는 대량의 태그 목록(애니메이션 이펙트 태그 등)을 태그 시스템으로 끌어온다.

 

 

 

2. [ Ability.Type.*  ]

+GameplayTagList=(Tag="Ability.Type.Action", DevComment="액션 스킬")
+GameplayTagList=(Tag="Ability.Type.Passive", DevComment="패시브 스킬")
+GameplayTagList=(Tag="Ability.Type.Info", DevComment="정보 조회 UI 스킬")
+GameplayTagList=(Tag="Ability.Type.StatusChange.Death", DevComment="사망 상태 전환")

GAS(Gameplay Ability System) 어빌리티의 속성과 역할을 분류하는 파트.

 

라이라의 설계 의도: 스킬 실행 시 "이 스킬이 직접 조작하는 액션인가?", "상시 켜져 있는 패시브인가?", "사망/스폰 상태 전환인가?"를 태그 단위로 구분하여 쿨타임이나 스턴 상태일 때 어떤 스킬을 차단(Block)할지 결정한다.

 

3. [ InputTag.*  ]

+GameplayTagList=(Tag="InputTag.Ability.Dash")
+GameplayTagList=(Tag="InputTag.Weapon.Fire")
+GameplayTagList=(Tag="InputTag.Weapon.Reload")

라이라의 최고 강점 중 하나로, 키보드/마우스 입력(Enhanced Input)과 C++ 스킬(GAS)을 결합도 0%로 연결해 주는 매개체이다.

 

라이라의 작동 원리: C++ 코드에 InputTag.Weapon.Fire라는 태그를 심어두면, 유저가 마우스 좌클릭을 누를 때 해당 태그를 품고 있는 WeaponFire 어빌리티가 자동으로 트리거된다. (C++에 특정 키 입력을 직접 작성하지 않음)

 

4. [ UI.Layer.*  ]

+GameplayTagList=(Tag="UI.Layer.Game")       ; 인게임 HUD
+GameplayTagList=(Tag="UI.Layer.GameMenu")   ; 영지/마을 상점, 인벤토리
+GameplayTagList=(Tag="UI.Layer.Menu")       ; 메인 메뉴
+GameplayTagList=(Tag="UI.Layer.Modal")      ; 최상단 다이얼로그/확인 팝업

CommonUI 프레임워크에서 화면 상의 UI 우선순위(Stack/Layer)를 통제하는 표준 태그파트.

 

라이라의 작동 원리: 새로운 UI 위젯을 띄울 때 "이 UI는 UI.Layer.Modal에 띄워라"라고 태그를 전달하면, UI 매니저 서브시스템이 아래 레이어의 입력을 차단하고 팝업창을 최상단에 얹어준다.

 

 

5. [ *.Message  ]

+GameplayTagList=(Tag="Lyra.Damage.Taken.Message")
+GameplayTagList=(Tag="Ability.Dash.Duration.Message")
+GameplayTagList=(Tag="ShooterGame.GamePhase.MatchBeginCountdown")

객체 간 Direct 참조 없이 이벤트를 방송하는 GameplayMessageSubsystem의 주파수(Channel) 역할을 하는 파트.

 

라이라의 작동 원리: 데미지 컴포넌트가 Lyra.Damage.Taken.Message 태그 채널로 "나 50 데미지 받았음" 신호를 쏘면, 체력바 UI나 사운드 시스템이 그 라디오 주파수를 수신(Listen)하여 체력바를 줄이고 악 소리를 낸다.

 

 

6. [ GameplayCue.* & GameplayEffect.*  ]

이펙트 및 연출 태그파트.

+GameplayTagList=(Tag="GameplayCue.Weapon.Rifle.Fire")
+GameplayTagList=(Tag="GameplayEffect.DamageType.Pistol")

라이라의 작동 원리: C++에서 이펙트 생성 코드를 짜지 않고, GameplayCue.Weapon.Rifle.Fire 태그를 발사하는 순간 라이라의 Cue 매니저가 사전 등록된 이펙트/사운드 BP를 자동 실행한다.

 

...===...

 

<DefaultGameplayTags.ini 체크리스트>

 

프로젝트(탑다운 쿼터뷰 RPG + 오토배틀러 + 영지 경영 + 대화형 시나리오)의 4단계 루프를 받쳐주기 위해 반드시 추가/정리해야 할 태그 체계를 살펴보자.

 

영지 경영 & 하루 마감 이벤트 메시지 태그 (Message.Dga.*)

Message.Dga.Time.AdvanceDay: AdvanceDay() 가동 시 날짜 변경 방송.

Message.Dga.Settlement.GoldUpdated: 주점 수입 / 용병 일당 차감 정산 완료 방송.

 

이원화 대화 & 인카운터 태그 (UI.Dialogue.*, Interaction.*)

UI.Layer.DialogueBubble: 탑다운 시점 몬스터/NPC 말풍선 UI.

UI.Layer.DialogueTyping: 하단 전면 대화 타이핑 UI.

 

오토배틀 AI & 3인칭 직접 조작 태그 (InputTag.*, Ability.Type.*)

InputTag.Tactical.Select: 탑다운 모드 유닛/가구 클릭.

InputTag.Combat.WASD.Skill: 3인칭 전환 시 직접 스킬 카운터 발동.

Ability.Type.Passive.HousingBuff: 주점 하우징 배치 버프

 

...===...

 

<GameplayTags 작성 요령>

1. 판단 기준: bool / Enum vs GameplayTag

기능을 구현할 때 아래의 질문을 던져보자.

                       [이 데이터/상태는 누구의 것인가?]
                                     │
            ┌────────────────────────┴────────────────────────┐
            ▼                                                 ▼
 [오직 내 C++ 클래스 내부에서만]                    [다른 클래스/UI/이펙트/입력에서]
 [검사하고 외부 통신이 없다]                       [조회하거나, 반응하거나, 차단해야 한다]
            │                                                 │
            ▼                                                 ▼
     bool / Enum 사용                                 GameplayTag 사용
(예: bIsGrounded, EDoorState)                   (예: Status.Stunned, InputTag.Fire)

 

> bool / Enum을 써야 하는 경우 (단공성 상태) :

 

이 변수 값이 바뀌어도 내 클래스 내부의 C++ 코드에서만 알면 될 때.

절대로 새로운 타입이 추가될 일이 없을 때 (예: 2D/3D 선택, 참/거짓 플래그).

 

> GameplayTag를 써야 하는 경우 (확장성 및 디커플링) :

 

내가 만든 상태가 다른 파트(UI, AI, 사운드, 이펙트, 스킬)에 연쇄 반응을 일으켜야 할 때.

Enum을 쓰면 나중에 C++ 헤더 파일을 고치고 재컴파일해야 하지만, 태그를 쓰면 기획자나 타 파트원이 데이터 에셋/블루프린트에서 수정을 완결지을 수 있을 때.

 

2. C++ 코드 작성 시 체크리스트 (태그를 붙여야 하는 6대 포인트)

 

코딩을 할 때 다음 6가지 상황에 해당한다면 "아! 여기엔 태그를 심어야겠구나" 하고 체크리스트를 키면 된다.

 

>> Point 1. 입력과 행동을 연결할 때 (InputTag.*)

 

상황: 키보드/마우스/패드 버튼 입력으로 스킬이나 동작이 나갈 때.

 

이유: C++ 코드에 EKeys::LeftMouseButton 같은 물리 키를 적지 않고 InputTag.Weapon.Fire 태그를 적어두면, 타 파트(기획/UI)에서 향상된 입력(Enhanced Input) 세팅에서 키를 마음대로 바꿀 수 있다.

 

>> Point 2. 행동을 차단(Block)하거나 허용(Allow)해야 할 때 (Status.*, Ability.Type.*)

 

상황: "기절(Stun) 상태일 때는 이동과 공격이 안 되어야 해!", "스킬 쿨타임 중이야!"

 

이유: GAS(Gameplay Ability System)에서는 Status.Stunned 태그가 캐릭터에 붙어있는 동안 Ability.Type.Action 태그를 가진 모든 스킬의 실행을 C++ 코드 수정 없이 자동으로 차단해 준다.

 

>> Point 3. 다른 시스템에 "나 이거 했어!"라고 소문내야 할 때 (Message.*)

 

상황: "체력이 깎였음", "하루 마감이 끝났음(AdvanceDay)", "아이템을 획득했음".

 

이유: GameplayMessageSubsystem을 통해 Message.Dga.Time.AdvanceDay 태그 채널로 신호를 쏘면, 용병 정산 시스템이나 UI가 C++ #include로 얽히지 않고 라디오 주파수처럼 신호를 받아 처리한다.

 

>> Point 4. 화면에 UI 팝업이나 레이어를 띄울 때 (UI.Layer.*)

 

상황: 마을 상점창, 하단 타이핑 대화창, 하루 마감 정산서 팝업을 띄울 때.

 

이유: CommonUI 매니저에 UI.Layer.Modal 태그를 넘겨주면 C++ 코드 없이 최상단 뎁스(Depth) 조절과 밑 레이어 클릭 차단을 엔진이 알아서 처리해 준다.

 

>> Point 5. 사운드, 이펙트, 애니메이션 연출을 틀어야 할 때 (GameplayCue.*)

 

상황: 총을 쐈을 때 피격 이펙트/사운드를 출력하거나 재질별 발자국 소리를 낼 때.

 

이유: C++에서 이펙트 에셋을 직접 로드해 UGameplayStatics::SpawnEmitterAtLocation을 호출하지 않고, GameplayCue.Weapon.Rifle.Fire 태그만 터트려주면 아티스트가 에디터에서 이펙트를 뗐다 붙였다 할 수 있다.

 

>> Point 6. 데이터 에셋을 카테고리별로 분류/필터링할 때 (Item.Type.*, Mercenary.Trait.*)

 

상황: 용병의 성향(지휘관형/선봉장형), 장비 종류(무기/방어구/가구)를 나눌 때.

 

이유: C++ Enum 대신 태그로 분류해 두면, 나중에 "마법 무기"나 "하우징 특화 용병" 같은 신규 카테고리가 생겨도 C++ 코드를 재컴파일하지 않고 .ini나 에디터에서 태그만 추가하면 된다.

 

 

3. 프로젝트에서 태그 관리 및 C++ 선언 및 노하우

 

1) 예측하지 말고 '표준 규칙'대로 이름만 짓기

 

태그를 어디에 쓸지 당장 몰라도 괜찮다. 계층 구조 규칙만 지켜서 적어두면 나중에 다른 파트에서 자석처럼 끌어다 쓴다.

 

규격: 카테고리.세부시스템.동작/상태

 

예시: Dga.Time.AdvanceDay, Ability.Type.Action.CounterSkill

 

2) 오타 방지를 위한 C++ 전용 Native Tag 선언 (FNativeGameplayTags)

 

C++ 코드 내부에서 "Ability.Type.Action" 같은 문자열을 직접 하드코딩하면 오타가 나기 쉽다. 다음과 같이 C++ 상수에 태그를 매핑해 두자.

// NativeGameplayTags.h (C++ 선언)
#include "NativeGameplayTags.h"

namespace DgaGameplayTags
{
    // C++ 컴파일 타임에 안전하게 검증되는 Native Tag 선언
    UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_Type_Action);
    UE_DECLARE_GAMEPLAY_TAG_EXTERN(Message_Time_AdvanceDay);
}

// NativeGameplayTags.cpp (C++ 정의)
namespace DgaGameplayTags
{
    UE_DEFINE_GAMEPLAY_TAG(Ability_Type_Action, "Ability.Type.Action");
    UE_DEFINE_GAMEPLAY_TAG(Message_Time_AdvanceDay, "Message.Dga.Time.AdvanceDay");
}

이렇게 해두면 C++ 상에서 DgaGameplayTags::Ability_Type_Action으로 안전하게 사용하면서, 에디터 및 .ini 파일과 자동 연동된다.

 

==============================

>>> 요약 체크리스트

[내가 만들고 있는 기능 태그 체크리스트]

[ ] 확장성: 나중에 이 상태/종류에 새로운 타입이 추가될 가능성이 있는가?

[ ] 외부 연동: 다른 파트(UI, 이펙트, 사운드, 타 C++ 클래스)에서 이 이벤트를 감지해야 하는가?

[ ] 입력 디커플링: 특정 키 조작이 직접 C++ 함수를 부르지 않고 스킬/행동을 인자로 전달받는가?

[ ] 상태 제어: 이 상태일 때 다른 스킬이나 이동을 차단(Block)해야 하는가?

 

위 항목 중 단 하나라도 'YES'라면 C++ Enum 대신 GameplayTag를 채택한다.

==========================


*팀 프로젝트*

1. 디버깅 내용

 

[1. Nameplate 안뜨는 문제 수정]

 

 

[2. HOST 출력 오류 문제]

 

 

[3. 맵 이동 문제 수정]

 

2. 발표자료 만들기

 

[1. 클래스 다이어그램 ]

[2. 시퀀스 다이어그램 ]

 

[3. 서버-클라이언트 권한 ]



*오늘의 총평*

열심히 했다!!! 밥먹는 시간도 아껴가며 작업한 것 같다. 많이 배우고 있음!

'TIL' 카테고리의 다른 글

07.27 TIL  (0) 2026.07.27
07.24 TIL  (0) 2026.07.24
07.22 TIL  (0) 2026.07.22
07.21 TIL  (0) 2026.07.21
07.20 TIL  (0) 2026.07.20