2026-07-09 TIL (94일차)
언리얼 데디케이티드 서버 AWS 연동 테스트 및 EOS의 필요성 깨달음
오늘의 목표
- 언리얼 엔진 데디케이티드 서버를 패키징하여 AWS EC2 인스턴스에 올리고, 로컬 클라이언트에서 접속 테스트 진행.
- 현재 LAN(Null) 환경의 한계를 이해하고, EOS(Epic Online Services) 연동의 필요성 파악.
배운 내용 및 트러블 슈팅
1. 클라이언트 크래시 (Out of Memory) 해결
- 문제: 로컬 PC 한 대에서 에디터, 서버, 클라이언트 2개를 동시에 띄우고 테스트하다가 클라이언트가 알 수 없는 이유로 자꾸 꺼지는(Crash) 현상 발생.
- 원인 분석: 로그 확인 결과
error 8007000e(DirectX 12 메모리 부족 에러) 확인. RTX 3070(VRAM 8GB) 환경에서 레이 트레이싱을 켠 상태로 다수의 언리얼 인스턴스를 실행하여 VRAM이 초과됨. - 해결 방안: 클라이언트 실행 시 가벼운 그래픽 환경으로 강제 실행하는 인수를 추가하여 메모리 다이어트 진행.
- 적용 명령어:
-Client.exe -d3d11 -windowed -resx=1280 -resy=720 - 결과: 크래시 없이 쾌적하게 클라이언트 다중 실행 성공.
- 적용 명령어:
2. AWS EC2 데디케이티드 서버 세팅 및 직접 접속 테스트
- AWS EC2(t3.small)에 서버 빌드 파일 업로드 후 실행.
- 서버 실행 명령어:
CrazyRooServer.exe TestMap -log(GUI 없는 Headless 모드이므로 그래픽 옵션 불필요) - 방화벽 설정의 중요성: AWS 인스턴스의 ‘보안 그룹’과 내부 ‘Windows 방화벽’ 양쪽 모두 UDP 7777 포트를 허용해야 접속 가능함.
- 다이렉트 접속(콘솔 명령어): 아직 UI의 ‘방 찾기’ 기능이 인터넷 망에서 동작하지 않으므로, 클라이언트 콘솔(
~)을 열고open [AWS_퍼블릭_IP]:7777명령어로 다이렉트 접속 테스트 성공. - 방장 권한의 비밀: 데디케이티드 서버 환경에서는 [방 생성] 버튼을 누르든 콘솔로 접속하든, 빈 서버에 가장 먼저 접속한 사람(JoinOrder 1번)이 방장 권한을 획득함.
3. Null(LAN) 시스템의 한계와 EOS 연동의 필요성
오늘 가장 큰 깨달음을 얻은 부분. 왜 잘 만들어진 [방 검색] UI가 AWS 서버를 찾지 못했는가?
- 현재 (OnlineSubsystemNull): -
FindSessions실행 시, 로컬 공유기(LAN) 내부에 브로드캐스트를 날려 서버를 찾음. (“동네방네 소리치기”)- 외부 인터넷망에 있는 AWS 서버에는 신호가 닿지 않아 UI 목록에 표시되지 않음.
- 미래 (OnlineSubsystemEOS):
- 서버가 구동될 때 에픽게임즈 중앙 서버(매치메이킹 서버)에 자신의 IP를 스스로 등록함. (“공용 게시판 전단지 붙이기”)
- 클라이언트가
FindSessions호출 시, 로컬 망이 아닌 에픽게임즈 서버의 게시판을 읽어 방 목록을 가져옴. - 결론: IP가 매번 바뀌어도 개발자가 수동으로 등록할 필요 없이 코드가 알아서 처리해주며, 인터넷 환경에서도 UI의 ‘방 목록’이 정상 작동하게 됨.
내일 할 일 (To-Do)
- AWS EC2 사용 종료 후 과금 방지를 위해 반드시 인스턴스 [중지] 상태 확인하기.
- 현재 작성된 세션 UI 코드 구조 유지하면서 Phase 5 (EOS 연동) 작업 준비하기.
회고
처음엔 코드가 잘못된 줄 알고 당황했지만, 네트워크 검색 방식의 근본적인 차이(LAN vs 매치메이킹 서버)를 이해하고 나니 로드맵의 다음 단계가 왜 필요한지 명확해졌다. 로그 보는 법과 명령 줄 인수 활용법을 익힌 것도 큰 수확!
[TIL] Unreal Engine 5: 카오스 물리(Chaos Physics) 파괴 연출 시 즉시 증발 및 추락 문제 해결
1. 배경 및 문제 상황
러닝 게임에서 플레이어가 라인트레이스(총)로 장애물을 쏠 때, 파편이 튀며 산산조각 나는 연출(Geometry Collection)을 구현 중이었다. HP가 0이 되면 SetLifeSpan(3.0f)을 주어 3초 뒤에 액터가 삭제되도록 C++ 코드를 작성했으나, 두 가지 심각한 버그가 발생했다.
- 문제 1 (즉시 증발): 총으로 쏘자마자 3초를 기다리지 않고 파편이 즉시 화면에서 사라짐.
- 문제 2 (무한 추락): 파편들이 바닥(땅)에 부딪히지 않고 그대로 바닥을 뚫고 쑥 떨어져 버림.
2. 원인 분석
원인 1: 강한 임펄스 + 콜리전 꺼짐 → KillZ(월드 밖) 판정으로 자동 Destroy
- 파괴 시점에 조각을 흩어지게 하려고
Add Radial Impulse의 Strength를 500,000으로 매우 강하게 설정했음. - 이때 조각의 콜리전이 꺼져 있어서 바닥을 뚫고 지나갔고, 엄청난 속도로 월드 밑바닥(KillZ)을 벗어나버림.
- 결과적으로 엔진이 비정상 이탈로 간주하여 강제로
Destroy시켜버림 (EndPlay Reason=0). 즉,SetLifeSpan이 작동하기 전에 액터가 삭제된 것.
원인 2: 물리 파편의 콜리전 미설정
- 원본 메시를 숨기고 지오메트리 컬렉션을 보여줄 때, 파편 조각들이 바닥(WorldStatic)을 인식하게 만들어야 하는데
NoCollision상태로 두었음. 이로 인해 땅에 쌓이지 않고 그대로 추락함.
3. 해결책 및 구현 흐름
문제를 해결하기 위해 블루프린트(BP)의 노드 순서를 바로잡고, 임펄스 수치를 현실적으로 조정했다.
올바른 Blueprint (BP_PlayDestruction) 노드 순서
1
2
3
4
5
6
7
8
Event BP_PlayDestruction
├─> Set Visibility (True) // 파편 보이게 활성화
├─> Set Simulate Physics (True) // 물리 엔진 켜기
├─> Set Collision Enabled (Query and Physics) // ★ 핵심: 파편이 땅을 인식하도록 콜리전 켜기
├─> Crumble Active Clusters // 클러스터 강제 분해
└─> Add Radial Impulse
- Strength = 3000 // ★ 핵심: 50만에서 3천으로 대폭 낮춤 (우주 밖으로 날아감 방지)
- bVel Change = True
📌 C++ 로직 흐름 (정상 작동 확인)
C++ 구조 자체는 처음부터 문제가 없었으며, 철저하게 서버/클라이언트 및 로직과 연출을 분리한 구조다.
- 사격 명중:
FireByAimRay→ 장애물 HP 감소 → 0 도달 HandleDeath()(서버):Multicast_PlayDestruction()호출 → 델리게이트 브로드캐스트 →SetLifeSpan(3.0f)설정Multicast_PlayDestruction()(서버+클라): 원본 메시 숨김 & 콜리전 끔 →BP_PlayDestruction()이벤트 호출- BP 파괴 연출: 위에서 세팅한 순서대로 물리 파괴 연출 실행
- 정리: 3초 뒤 액터 전체
Destroy
4. 추가 이슈: 파편이 플레이어에게 데미지를 주거나 길을 막는다면?
파편에 Query and Physics를 켜면서 물리가 적용되었기 때문에, 이 파편들이 캐릭터를 밀거나 러닝 액션에 방해를 줄 수 있는 가능성이 생겼다.
Q. 파편에 맞으면 데미지를 입는가?
A. 입지 않는다. 데미지 판정은 원본 CollisionBox의 델리게이트를 통해 발생하는데, 파괴되는 순간(HandleDeath) 이 투명 박스의 콜리전과 Overlap 이벤트를 모두 꺼버리기 때문에 데미지 판정은 들어가지 않는다.
Q. 파편이 길을 막거나 밀어내는 물리적 방해는?
A. 발생할 수 있다. (해결 필요) 파편이 지형(바닥)에는 부딪히되, 플레이어(캐릭터)는 통과하도록 콜리전 채널을 세팅해야 한다.
[해결 방법] 지오메트리 컬렉션(Geometry Collection) 컴포넌트의 Collision Responses 세팅을 다음과 같이 조정한다.
WorldStatic= Block (바닥에 떨어져서 쌓임)Pawn= Ignore (플레이어 캐릭터는 파편을 그냥 뚫고 지나감)
5. 오늘 얻은 디버깅 교훈
- “내 코드를 추가하니까 이상해졌다”는 직감 믿기 문제가 발생했을 때, 새로 추가한 C++ 함수(
Multicast_PlayDestruction) 안의 로직을 하나씩 주석 처리해 가며 범인을 좁혀간 것이 가장 빠르고 정확한 접근이었다. - 변수 통제의 중요성 BP 노드를 하나씩 빼보면서 “임펄스를 빼니 추락만 하고”, “콜리전을 켜니 정상 작동한다”는 식으로 증상 변화를 체크한 것이 핵심이었다.
- EndPlay Reason 활용 디버깅 시 로그에 찍힌 파괴 이유(
Reason=0, 수동 파괴)를 확인하여 타이머에 의한 자연 소멸이 아님을 깨달은 것이 훌륭한 힌트가 되었다.