Sparta Unreal 부트캠프 70일차

정찬호·2026년 3월 12일

코딩 테스트

프로그래머스 - 롤케이크 자르기

문제 분석

케이크를 잘랐을 때 토핑 개수 상관없이 동일한 가지수의 토핑이 올라가면 케이크가 공평히 나누어진 것으로 취급

중복 상관 없이 종류수만 따지니 unordered_set?

토핑 종류마다 개수를 기록해두고 한칸씩 전진하며 unordered_set에 넣고 개수 감소 시킨 뒤 개수가 0이 아닌 토핑 종류의 수와 unordered_set의 크기를 비교해서 일치하면 answer 증가시키면 해결될 것 같네요.

해결 코드

#include <string>
#include <vector>
#include <unordered_set>

using namespace std;

int solution(vector<int> topping) {
    int answer = 0;
    unordered_set<int> toppingSet;
    vector<int> toppingCnt(10001, 0);
    for(int number:topping)
    {
        toppingCnt[number]++;
    }
    
    for(int i = 0; i < topping.size(); i++)
    {
        toppingSet.insert(topping[i]);
        toppingCnt[topping[i]]--;
        
        int currentCnt = 0;
        for(int cnt:toppingCnt)
        {
            if(cnt > 0)
            {
                currentCnt++;
            }
        }
        
        if(toppingSet.size() == currentCnt)
        {
            answer++;
        }
    }
    return answer;
}

TA 분반 복습

라이팅 채널 관련 내용 정정

라이팅 채널은 조명과 매쉬 양쪽에 존재하며 같은 채널의 경우에만 영향을 줍니다.

SpotLight는 가장 많이 사용하게 될 조명이라고 합니다.

조명 강도에 단위를 설정할 수 있는데 일반적으로 칸델라를 추천합니다.
실제로 물리적으로 처리할 때 대부분의 자료를 보고 비교할 때 칸델라를 많이 사용하니 칸델라를 사용한다고 합니다.

디퍼드 랜더링의 경우 GBuffer 안에서 라이트 처리를 다 저장을 하고 그림자가 어떻게 영역을 차지하겠다라는 것까지 다 저장해 놓고 연산을 처리하기 때문에 연산이 상대적으로 적게 들어갑니다.
물론 메시가 많아질 경우에는 그대로 부하가 당연히 들어갑니다.
외적으로 좀 들어간다고 합니다. 메모리가 많아지나까 버퍼에 올라갈게 많아져서 VRam을 많이 차지해가지고 좀 퍼포먼스가 떨어진다던지

너무 하이 폴리곤일 경우에는 나나이트를 활성화해서 사용하는 것이 좋습니다.
나나이트도 내부로직으로 LOD를 어떻게 처리하겠다 라는게 들어가기 때문에 로우 폴리곤일 경우 오히려 퍼포먼스를 더 잡아먹게 됩니다.
나나이트 자체가 실시간으로 메쉬를 건드리기 때문에 나무같은 경우에는 좀 지저분해질 수도 있습니다.
그림자가 좀 지저분해진다던지 그런 아트적인 영향을 끼치기도 하기 때문에 무조건 키는 것은 좋지 못합니다.

스캔 데이터는 하이 폴리곤인 경우가 많는데 언리얼 엔진에는 스캔 데이터로 매쉬가 올라가는 에셋들이 꽤 많습니다. 그런 것들은 나나이트로 뭉뚱그려서 처리하면 됩니다. 물론 패킹 될 때 용량이 많은 건 별개입니다.
Unity 같이 lod를 만들 수 있는 다른 툴을 통해 low polygon을 만드는 것도 방법 중 하나입니다.

플리커링(Flickering)

화면에서 빛/밝기가 프레임마다 미세하게 깜빡이거나(번쩍/흔들), 얼룩처럼 불안정하게 변하는 현상입니다.
카메라가 움직이거나, 이미시브가 얇거나(간판/LED 스트립), 패턴이 촘촘하거나, 밝기가 아주 강할 때 자주 발생합니다.

이미시브를 “조명처럼” 쓰면 플리커링이 생기는데, 그 이유는 이미시브는 원래 ‘표면이 밝게 보이는 것’이고, 이것을 주변을 실제로 비추는 ‘광원’처럼 만들려면 엔진이 추가 계산(간접광/GI)을 해야 하는데, 그 과정이 시간적으로/공간적으로 샘플링(대충 뽑아서 근사) 되는 경우가 많아서라고 합니다.

라이트 믹서 추가 설명

레벨에 배치된 전체 라이트가 표시되며 그 중에 일부를 골라서 볼 수도 있습니다.
라이트 컬러랑 라이트 채널이 어떻게 되어있는지, 어터네이션 변경 처리를 어떻게 할 지를 간단히 조절할 수 있습니다.
월드 아웃라이너에 배치된 폴더대로 분리되어 볼 수있다고 합니다.

조명에 머티리얼을 넣는 것은 특정 모양의 빛을 비추도록 필터를 씌우는 느낌, 배트맨의 배트 시그널(하늘에 박쥐 모양 조명)을 생각하면 될 것 같습니다.

구름이 낀 날씨, 물속에 윤수를 표현할 때 이런 머티리얼 펑션을 사용합니다.

Decal 만들기

Mateiral Domain = Deferred Decal - Decal 오브젝트를 만들 때 사용합니다.
Blend Mode = Translucent

Decal은 일종의 도장을 찍는 효과를 말합니다.
Decal 자체의 연산량이 진짜 적기 때문에 라이트로 쓰는 경우도 있습니다.
어떤 특정 영역에 캐릭터가 동적으로 움직일 것 같진 않은, 뭔가 그냥 정적으로 배치가 되어야 하는데 거기다가 라이트를 배치하자니 좀 부담스러울 때 Decal로 라이트를 처리해서 쓰기도 합니다.

액터 생성 창에 VisualEffects -> Decal Actor로 Decal 전용 액터 생성
재질하나 가져다 쓰는 게 아니라 데칼을 따라서 배치가 되는 액터?
데칼 액터에는 화살표가 있는데, 이 화살표 방향대로 데칼이 배치가 됩니다.

Unreal Engine 멀티플레이어 게임 개발 강의 수강

ThisClass
ThisClass는 지금 이 코드를 작성하고 있는 클래스 타입(클래스 자신)”을 가리키는 별칭(alias)입니다.
대부분의 경우 GENERATED_BODY() 매크로가 클래스 안에 ThisClass 별칭을 “생성”해준다고 합니다.

using ThisClass = UCXChatInput;

정확히는 언리얼의 UCLASS() + GENERATED_BODY() 조합은 UHT(Unreal Header Tool)가 코드를 생성/확장하면서, 클래스 내부에 관용적으로 아래 같은 typedef/using를 포함시키는 패턴이 있다고 합니다.

ThisClass : “현재 클래스 타입”
Super : “부모 클래스 타입”

ThisClass 사용시 장점

  • 리팩터링에 강함: 클래스 이름을 바꿔도 using ThisClass = ...만 수정하면, 아래 바인딩 코드들은 그대로 유지돼요.
  • 가독성: “이 함수는 이 클래스의 멤버 함수다”라는 의도가 더 또렷해져요.
  • 템플릿/매크로/바인딩 코드에서 흔함: Delegate 바인딩에서 &클래스명::함수 형태가 반복되니 짧게 쓰는 목적도 있어요.

서버의 종류 그 중에서도 데디케이트 서버
P2P

  • 각각의 PC가 클라이언트이자 서버
  • 철권의 매칭 대전 같은 경우, 서로가 연결되는 방식
  • 보안성이 취약합니다.

Listen Server

  • 어몽어스처럼 클라이언트 중 하나가 서버의 역할을 수행합니다.
  • P2P의 변경이라고도 볼 수 있을 겁니다.

Dedicated Server

  • 아예 서버의 역할에만 전념(Dedicate)하는 PC가 존재합니다.
  • 배틀그라운드, 아마도 MapleStory의 경우에도 해당될 것입니다.

Unreal에서의 DedicatedServer
PIE(Play In Editor)하거나 서버.exe를 실행하면 서버 프로세스가 실행됩니다.
데디케이트 서버 프로세스가 시작되고, 이 상태에서는 자동으로 다음과 같은 명령어가 호출됩니다.

Open{LeveL 이름}?Listen

이 때 Socket이 생성되며 다른 PC가 접속 가능하게끔 합니다. Listen 명령어가 없다면 싱글 플레이가 됩니다.

  • Socket : OS가 제공하는 네트워크 통신용 핸들입니다. 생성 시 프로토콜 타입을 선택합니다.
  • Port: IP 안에서 어떤 프로그램(프로세스/서비스)로 들어갈지 고르는 번호입니다. 통신 창구 번호로 이해해도 무방합니다.

통신을 받아들일 수 있도록 열린다.

Level에는 WorldSettings 속성이 있고, WorldSettings에는 GameMode와 GameState 정보가 있습니다.
이를 통해 GameMode와 GameState 액터를 생성합니다.
중요한 것은 GameMode는 서버에만 존재한다는 것입니다.
그래서 GameMode와 서버를 동일시해도 된다는 말이 생겼다고 합니다.

  1. 클라이언트는 서버의 IP주소와 포트번호로 접속을 시도합니다.
  2. 서버는 접속 시도하는 클라이언트한테 레벨 정보를 전달합니다.
  3. 클라이언트는 레벨을 연 뒤 Level을 여는데 성공했다고 서버에 알립니다.
  4. 성공 알림을 받은 서버는 그 클라이언트 전용 PlayerState, PlayerController, PlayerCharacter를 생성합니다.
  5. 생성된 객체들이 클라이언트에 복제됩니다.(GameStae도 복제됩니다)
  6. 다른 클라이언트가 접속 시 1~5가 다시 반복됩니다. 단, 다른 클라리언트에 복제되는 객체는 PlayerState와 PlayerCharacter까지 입니다.

여기서 클라이언트 간의 통신은 불가합니다.
클라이언트간의 상호작용을 하길 원한다면 서버를 거쳐야합니다.

Ctrl + T => 코드 서치

Todo

  • Challenge 분반 문서보면서 학습
  • TA 분반 볼륨과 Character Retarget 오류 해결
profile
게임 개발 지망생입니다.

0개의 댓글