영상을 불러오지 못했습니다

UE4→UE5 전환 후 AsyncLoading 재귀 assertion 진단

734 단어
4 분
UE4→UE5 전환 후 AsyncLoading 재귀 assertion 진단

UE4 프로젝트를 UE5로 전환한 뒤 editor에서는 동작하지만 패키징 빌드 로드 중 다음 assertion으로 종료되는 문제가 있었다.

AsyncLoadingThread.RecursionNotAllowed.Increment() == 1

문제 현상#

특정 map 또는 asset 묶음을 비동기로 불러올 때 AsyncLoading thread가 처리 중이던 로드 구간에 다시 진입해 assertion이 발생했다. UE4에서 선택적으로 쓰던 Event Driven Loader 설정과 UE5의 기본 로드 경로 차이 때문에 전환 직후 드러나기도 한다.

적용 범위#

UE4에서 UE5로 asset과 custom C++ serialization 코드를 함께 이관한 뒤 cooked build에서만 재현되는 경우를 다룬다. 원문에는 최종 offending asset이 남아 있지 않으므로 확정 해법이 아닌 진단 초안으로 유지한다.

가능한 원인#

  • Serialize, PostLoad 또는 UObject constructor에서 동기 asset load를 호출한다.
  • async load completion callback이 같은 package를 다시 동기로 요청한다.
  • custom archive/loader가 thread-safe하지 않은 전역 상태를 사용한다.
  • 오래된 cooked output이나 redirect가 다른 package graph를 만든다.
  • custom engine 수정이 UE5 AsyncLoading2 경로와 맞지 않는다.

재현 및 진단#

  1. assertion 전 전체 call stack과 마지막으로 로드한 package 이름을 수집해 둔다.
  2. LoadObject, StaticLoadObject, TryLoad, synchronous streamable handle 호출을 검색한다.
  3. 이 호출이 constructor, Serialize, PostLoad와 async callback 안에서 실행되는지 나눠 본다.
  4. 문제가 되는 map의 asset dependency를 줄여 최소 재현 package를 찾아낸다.
  5. stale cooked output을 배제한 clean cook에서 다시 확인해 본다.
  6. custom engine이라면 exact upstream revision과 AsyncLoading 관련 diff도 비교한다.

해결 방법#

로드 도중 다시 진입하는 동기 load를 제거하고 dependency를 soft reference와 상위 단계의 명시적 async request로 옮긴다. callback에서는 이미 완료된 object를 사용하고 같은 package graph를 다시 로드하지 않는다.

잘못된 asset reference나 redirect가 원인이라면 해당 asset을 새 버전에서 다시 저장하고 redirect를 정리한 뒤 전체 recook한다. assertion 자체를 끄거나 EDL 동작을 억지로 과거 방식으로 되돌리면 상태 손상을 숨길 우려가 있어 해결책으로 보지 않는다.

검증 방법#

  • editor, standalone과 packaged build에서 동일한 map 순서를 반복해 본다.
  • cold start와 이미 asset cache가 채워진 두 상황을 시험한다.
  • 여러 번의 level transition과 비동기 취소 경로를 확인해 둔다.
  • package 이름을 포함한 로드 로그에서 같은 package의 재진입이 사라졌는지 살펴본다.

주의점#

call stack만으로 “UE5에서는 EDL이 항상 켜져서 생긴다”고 단정할 수 없다. UE5의 async loading 구현도 minor version마다 바뀌므로 exact engine source를 확인하며 조사해야 한다.

참고 자료#

글 공유하기

이 글이 도움이 되셨다면 다른 사람과 공유해 주세요!

UE4→UE5 전환 후 AsyncLoading 재귀 assertion 진단
https://hon454.github.io/posts/ue5-async-loading-recursion-edl-migration/
작성자
Jihoon Jeon
게시일
2023-11-03
라이선스
CC BY-NC-SA 4.0
관련 게시글스마트
1
면접 오답노트: 말하지 못한 주요 개념, Net Relevancy
Unreal Engine면접에서 제대로 답하지 못한 Net Relevancy를 다시 정리한다. AActor::IsNetRelevantFor의 판정 순서와 문서와 다른 부분, Owner가 판정을 바꾸는 방식, 연관성을 잃고 되찾을 때 RelevantTimeout과 액터 파괴, BeginPlay, OnRep, RPC에 생기는 일, ForceNetRelevant와 Replication Graph, Iris에서의 주의점, Dormancy, Priority와의 차이를 다룬다.
2
언리얼 엔진의 리플리케이션 및 RPC 순서 보장
Unreal Engine프로퍼티 복제와 OnRep, RPC의 순서 보장 범위를 살펴보고, 일시적인 상태 불일치와 액터 간 준비 순서를 처리하는 방법을 예시로 정리한다.
3
[노트] Unreal Engine Skills for Claude Code
Unreal EngineEpic Games가 공개한 Claude Code 플러그인 Unreal Engine Skills for Claude Code의 스킬 3개와 SessionStart 훅을 읽고, 스킬의 트리거 설계와 문서화 규칙, 엔진 쪽 Agent Skill, 보안 경고의 범위, MCP와 스킬의 역할 분담, Claude Code용만 나온 점에 대한 생각을 정리한다.
4
언리얼 엔진 5.8 MCP로 본 게임 개발과 에이전틱 코딩의 거리
Unreal Engine언리얼 엔진 5.8 MCP를 Claude Code와 Codex로 써 보고 Epic 세션을 보며, All Toolsets에 이미 포함된 Editor Toolset, 일괄 작업과 비용, 에디터 의존성, 프로젝트 구조 지식의 필요성에 대해 생각한 점을 정리한다.
5
Night of the Dead 멀티플레이를 지금 다시 설계한다면
Unreal EngineNight of the Dead의 멀티플레이 최적화를 새 프로젝트에서 처음부터 설계한다면 바꿀 부분을 좀비의 Mass 전환, Push Model과 Fast Array와 연결별 서브오브젝트 필터를 쓰는 복제, 애플리케이션 계층의 전송 흐름 제어로 나눠 기존 코드와 비교한다.
무작위 게시글무작위

댓글

Profile Image of the Author
Jihoon Jeon
안녕하세요! 서브컬처와 자전거를 사랑하는 개발자 전지훈입니다.
공지사항
제 블로그에 오신 것을 환영합니다! 예시 공지입니다.
카테고리
태그
최신 일상
사이트 통계
게시글
73
카테고리
10
태그
143
총 단어 수
133,527
운영 일수
0일
최근 활동
0일 전
사이트 정보
빌드 플랫폼
GitHub Actions
블로그 버전
Firefly v6.16.9
라이선스
CC BY-NC-SA 4.0
목차