UNREAL · 게임 시스템
세이브를 불러오니 퀘스트 완료 알림이 다시 다 떴다
세이브를 불러오면 예전에 이미 깬 퀘스트 단계들의 완료 알림이 화면에 우르르 다시 떴다. 진행은 제대로 복원됐는데 알림만 새로 완료한 것처럼 튄 거다. 원인은 상태 복원을 상태 전이랑 같은 경로로 처리한 데 있었다.
목표
저장된 퀘스트 단계를 복원할 때, 이미 완료했던 단계들이 ‘방금 완료됨’으로 잡혀 알림이 다시 뜨는 걸 막는다.
원인 — 완료 처리 함수가 상태 전이와 알림을 묶어 놨다
UQuestBranchComponent::CompleteStep이 상태 전이 + 알림 브로드캐스트를 한 함수에 묶고 있었다. 세이브에 담긴 완료 단계들을 복원하면서 이 경로를 그대로 다시 태우니, 알림 서브시스템이 복원된 단계 전부를 ‘새로 완료된 것’으로 인식해 알림을 쏴 버렸다. 정상 플레이용 진입점을 복원에도 재사용한 게 화근이었다.
해결 — 복원 전용 경로를 따로 판다
- 복원 전용 API 분리:
MakeQuestSaveData()/ApplyQuestSaveData()가 알림 없이 상태만 덮어쓴다. - 알림 기준선 재설정:
LastSeenCompletedSteps = CompletedSteps;로 맞춰, 복제 클라에서OnRep_CompletedSteps가 다시 튀지 않게 한다. - 호출자(SaveSubsystem)가 복원 직후
QuestNotificationSubsystem->ResetBaseline()을 부르고, UI 갱신 신호(Channel_Quest_StepChanged)는 딱 한 번만 브로드캐스트한다.
요점은 ‘개별 이벤트 재생’과 ‘최종 상태 알림’을 분리한 것이다. 복원은 최종 상태만 맞추면 되지, 거기 도달한 과정을 다시 이벤트로 쏠 필요가 없다.
배운 점
상태 복원은 상태 전이와 다르다. 게임플레이 진입점(여기선 CompleteStep)은 알림·검증 같은 부수효과를 항상 끼고 있다. 그걸 복원에 그대로 쓰면 부수효과까지 재생된다.
복원 전용 API는 부수효과를 떼어내는 대신, 호출자가 무엇을 책임지는지(기준선 리셋, UI 한 번 갱신)를 문서로 못 박아야 한다. 안 그러면 다음 사람이 또 진입점을 재사용한다.