๐Ÿ“˜TIL - ๋ชจ๋‹ฅ๋ถˆ ๊ธฐ๋ฐ˜ ์ €์žฅ ยท ์ œ์ž‘ ยท ๋น ๋ฅธ ์ด๋™ ์‹œ์Šคํ…œ ์„ค๊ณ„ ๋ฐ ๊ตฌํ˜„

HappyCircleยท2026๋…„ 5์›” 29์ผ

Unreal ๊ฐœ๋ฐœ

๋ชฉ๋ก ๋ณด๊ธฐ
136/163

๋ฐฐ๊ฒฝ

ํ˜„์žฌ ํ”„๋กœ์ ํŠธ๋Š” ์ธ๋ฒคํ† ๋ฆฌ, ์žฅ์ฐฉ, ์•„์ดํ…œ ํš๋“, ์ƒํ˜ธ์ž‘์šฉ ์‹œ์Šคํ…œ์ด ๊ฐ๊ฐ ๋…๋ฆฝ์ ์œผ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ๋Š” ์ƒํƒœ์˜€๋‹ค.

ํ•˜์ง€๋งŒ RPG์—์„œ๋Š” ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ํƒํ—˜ โ†’ ์ „ํˆฌ โ†’ ๋ณด์ƒ ํš๋“ โ†’ ์„ฑ์žฅ โ†’ ๋‹ค์Œ ์ง€์—ญ ์ง„์ž…์ด๋ผ๋Š” ํ๋ฆ„์„ ๋ฐ˜๋ณตํ•˜๊ฒŒ ๋˜๋Š”๋ฐ, ์ด๋ฅผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ๊ฑฐ์  ์‹œ์Šคํ…œ์ด ํ•„์š”ํ–ˆ๋‹ค.

์ด๋ฒˆ ์ž‘์—…์—์„œ๋Š” ๋ชจ๋‹ฅ๋ถˆ์„ ๋‹จ์ˆœ ์ฒดํฌํฌ์ธํŠธ๊ฐ€ ์•„๋‹Œ ๊ฒŒ์ž„ ์ง„ํ–‰์˜ ์ค‘์‹ฌ ํ—ˆ๋ธŒ๋กœ ํ™œ์šฉํ•˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๊ตฌ์กฐ๋ฅผ ์ •๋ฆฌํ–ˆ๋‹ค.

๋ชจ๋‹ฅ๋ถˆ์„ ํ†ตํ•ด ๋‹ค์Œ ๊ธฐ๋Šฅ๋“ค์„ ํ†ตํ•ฉํ•˜๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ์˜€๋‹ค.

์ €์žฅ
์ œ์ž‘
๋น ๋ฅธ ์ด๋™
์ง„ํ–‰ ์ƒํƒœ ๋ณต์›

๋˜ํ•œ ์ถ”ํ›„ ํ€˜์ŠคํŠธ, ์„ ํƒ ๊ธฐ๋ก, ์—”๋”ฉ ๋ถ„๊ธฐ, ์˜๊ตฌ ์›”๋“œ ์ƒํƒœ ์ €์žฅ๊นŒ์ง€ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ์ €์žฅ ๊ตฌ์กฐ ์ž์ฒด๋ฅผ ํ•จ๊ป˜ ์„ค๊ณ„ํ–ˆ๋‹ค.


์ €์žฅ ์‹œ์Šคํ…œ ๊ตฌ์กฐ ์„ค๊ณ„

์ฒ˜์Œ์—๋Š” ์ธ๋ฒคํ† ๋ฆฌ๋งŒ ์ €์žฅํ•˜๋Š” ๋‹จ์ˆœ SaveGame ๊ตฌ์กฐ๋ฅผ ์ƒ๊ฐํ–ˆ์ง€๋งŒ, ์‹ค์ œ RPG์—์„œ๋Š” ์ €์žฅํ•ด์•ผ ํ•˜๋Š” ๋ฐ์ดํ„ฐ ์ข…๋ฅ˜๊ฐ€ ๊ณ„์† ๋Š˜์–ด๋‚œ๋‹ค.

์ธ๋ฒคํ† ๋ฆฌ
์žฅ์ฐฉ ๋ฌด๊ธฐ
ํ€ต์Šฌ๋กฏ
ํ”Œ๋ ˆ์ด์–ด ์œ„์น˜
์ง„ํ–‰๋„
์„ ํƒ ๊ธฐ๋ก
์—”๋”ฉ ๋ถ„๊ธฐ
์›”๋“œ ์ƒํƒœ

์ด ๋•Œ๋ฌธ์— ์ฒ˜์Œ๋ถ€ํ„ฐ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ํ˜•ํƒœ๋กœ ์ €์žฅ ๊ตฌ์กฐ๋ฅผ ๋ถ„๋ฆฌํ–ˆ๋‹ค.

ํ˜„์žฌ MVP ๋‹จ๊ณ„์—์„œ๋Š” ๋‹ค์Œ ๋‘ ๋ ˆ์ด์–ด๋ฅผ ์šฐ์„  ์ €์žฅํ•˜๋„๋ก ๊ตฌ์„ฑํ–ˆ๋‹ค.

LoadSnapshot
โ””โ”€ ํ”Œ๋ ˆ์ด์–ด ๋ณต์› ๋ฐ์ดํ„ฐ

InventoryProgress
โ””โ”€ ์ง„ํ–‰ ๋ฐ์ดํ„ฐ

LoadSnapshot์—๋Š” ๋‹ค์Œ ์ •๋ณด๊ฐ€ ์ €์žฅ๋œ๋‹ค.

ํ”Œ๋ ˆ์ด์–ด Transform
ํ˜„์žฌ HP
์žฅ์ฐฉ ๋ฌด๊ธฐ
๋งˆ์ง€๋ง‰ ๋ชจ๋‹ฅ๋ถˆ ID

InventoryProgress์—๋Š” ๋‹ค์Œ ์ •๋ณด๊ฐ€ ์ €์žฅ๋œ๋‹ค.

์ธ๋ฒคํ† ๋ฆฌ
ํ€ต์Šฌ๋กฏ
์ง„ํ–‰ ํƒœ๊ทธ
์„ ํƒ ๊ธฐ๋ก

์ถ”ํ›„ ์˜ค๋ธŒ์ ํŠธ ๊ณ ์œ  ID ์ฒด๊ณ„๊ฐ€ ์™„์„ฑ๋˜๋ฉด PersistentWorldState ๋ ˆ์ด์–ด๋ฅผ ์ถ”๊ฐ€ํ•ด ์›”๋“œ ์ƒํƒœ๊นŒ์ง€ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋„๋ก ํ™•์žฅ ์ง€์ ์„ ๋‚จ๊ฒจ๋‘์—ˆ๋‹ค.


SaveSubsystem ๊ตฌ์กฐ ์ •๋ฆฌ

์ €์žฅ ๋กœ์ง์€ GameInstanceSubsystem ๊ธฐ๋ฐ˜์˜ SaveSubsystem์œผ๋กœ ๋ถ„๋ฆฌํ–ˆ๋‹ค.

๊ธฐ์กด์ฒ˜๋Ÿผ ์บ๋ฆญํ„ฐ๋‚˜ ํ”Œ๋ ˆ์ด์–ด ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ง์ ‘ ์ €์žฅ์„ ์ˆ˜ํ–‰ํ•˜๋ฉด ๊ธฐ๋Šฅ์ด ๋Š˜์–ด๋‚ ์ˆ˜๋ก ์˜์กด์„ฑ์ด ์ปค์งˆ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์—ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ €์žฅ๊ณผ ๊ด€๋ จ๋œ ๊ธฐ๋Šฅ์€ ๋ชจ๋‘ SaveSubsystem์ด ๋‹ด๋‹นํ•˜๋„๋ก ์ •๋ฆฌํ–ˆ๋‹ค.

SaveAtBonfire()
LoadGame()

MarkBonfireActivated()

FastTravelToBonfire()

ํŠนํžˆ ํ•จ์ˆ˜ ์ž…๋ ฅ์„ Actor๊ฐ€ ์•„๋‹Œ PlayerController ๊ธฐ๋ฐ˜์œผ๋กœ ๋ณ€๊ฒฝํ–ˆ๋‹ค.

SaveAtBonfire(APlayerController*)
LoadGame(APlayerController*)

์ด ๊ตฌ์กฐ ๋•๋ถ„์— ์ถ”ํ›„ ๋ฉ€ํ‹ฐํ”Œ๋ ˆ์ด ํ™•์žฅ ์‹œ ํ”Œ๋ ˆ์ด์–ด๋ณ„ Save Slot ๋ถ„๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์กŒ๋‹ค.


๋ชจ๋‹ฅ๋ถˆ ํ™œ์„ฑํ™” ์‹œ์Šคํ…œ ๊ตฌํ˜„

๋ชจ๋‹ฅ๋ถˆ์€ ๋‹จ์ˆœ ์ €์žฅ ์ง€์ ์ด ์•„๋‹ˆ๋ผ ๋น ๋ฅธ ์ด๋™ ๊ฑฐ์  ์—ญํ• ๋„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•œ๋‹ค.

๊ทธ๋ž˜์„œ ๋ชจ๋‹ฅ๋ถˆ์ด ํ™œ์„ฑํ™”๋˜๋ฉด ๋‹ค์Œ ์ •๋ณด๊ฐ€ SaveGame์— ๊ธฐ๋ก๋˜๋„๋ก ๊ตฌ์„ฑํ–ˆ๋‹ค.

BonfireId
ArrivalTransform

์ดˆ๊ธฐ์—๋Š” ๋‹จ์ˆœํžˆ ํ™œ์„ฑํ™” ์—ฌ๋ถ€๋งŒ ์ €์žฅํ•˜๋ ค๊ณ  ํ–ˆ์ง€๋งŒ, ๋น ๋ฅธ ์ด๋™์„ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ์‹ค์ œ ๋„์ฐฉ ์œ„์น˜๊ฐ€ ํ•„์š”ํ–ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๊ธฐ์กด ๊ตฌ์กฐ์˜€๋˜

TArray<FName> ActivatedBonfireIds

๋ฅผ

TMap<FName, FTransform>

์œผ๋กœ ๋ณ€๊ฒฝํ–ˆ๋‹ค.

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ชจ๋‹ฅ๋ถˆ ID์™€ ์‹ค์ œ ๋„์ฐฉ ์œ„์น˜๋ฅผ ํ•จ๊ป˜ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๊ณ , ๊ฒŒ์ž„ ์žฌ์‹œ์ž‘ ์ดํ›„์—๋„ ํ™œ์„ฑํ™” ์ƒํƒœ๋ฅผ ๊ทธ๋Œ€๋กœ ๋ณต์›ํ•  ์ˆ˜ ์žˆ๋‹ค.


์ œ์ž‘ ์‹œ์Šคํ…œ ๊ตฌ์ถ•

์ œ์ž‘ ์‹œ์Šคํ…œ์€ ๋ชจ๋‹ฅ๋ถˆ ๋ฉ”๋‰ด ์•ˆ์—์„œ ๋™์ž‘ํ•˜๋„๋ก ๊ตฌ์„ฑํ–ˆ๋‹ค.

ํ•ต์‹ฌ ๋ชฉํ‘œ๋Š” ๋ ˆ์‹œํ”ผ ์ถ”๊ฐ€๋งŒ์œผ๋กœ ์ œ์ž‘ ์•„์ดํ…œ์„ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด DataTable ๊ธฐ๋ฐ˜ ๋ ˆ์‹œํ”ผ ๊ตฌ์กฐ๋ฅผ ์„ค๊ณ„ํ–ˆ๋‹ค.

ํ•„์š” ์žฌ๋ฃŒ
๊ฒฐ๊ณผ ์•„์ดํ…œ
์ง„ํ–‰ ์กฐ๊ฑด

์ œ์ž‘ ํ๋ฆ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

๋ ˆ์‹œํ”ผ ์„ ํƒ
โ†“
์žฌ๋ฃŒ ๋ณด์œ ๋Ÿ‰ ๊ฒ€์‚ฌ
โ†“
์žฌ๋ฃŒ ์ฐจ๊ฐ
โ†“
๊ฒฐ๊ณผ ์•„์ดํ…œ ์ง€๊ธ‰
โ†“
์ธ๋ฒคํ† ๋ฆฌ ๊ฐฑ์‹ 

ํ˜„์žฌ๋Š” ์†Œ๋ชจ ์•„์ดํ…œ ์ œ์ž‘๋งŒ ์ง€์›ํ•˜์ง€๋งŒ, ๋™์ผํ•œ ๊ตฌ์กฐ๋ฅผ ์ด์šฉํ•˜๋ฉด ์ถ”ํ›„ ๋ฌด๊ธฐ ์ œ์ž‘์ด๋‚˜ ๊ฐ•ํ™” ์‹œ์Šคํ…œ๋„ ํ™•์žฅ ๊ฐ€๋Šฅํ•˜๋„๋ก ์„ค๊ณ„ํ–ˆ๋‹ค.


์›”๋“œ๋งต ๊ธฐ๋ฐ˜ ๋น ๋ฅธ ์ด๋™ ๊ตฌํ˜„

๋น ๋ฅธ ์ด๋™์€ ์›”๋“œ๋งต๊ณผ ๋ชจ๋‹ฅ๋ถˆ ์‹œ์Šคํ…œ์„ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉํ–ฅ์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค.

ํ™œ์„ฑํ™”๋œ ๋ชจ๋‹ฅ๋ถˆ๋งŒ ์›”๋“œ๋งต์—์„œ ์ด๋™ ๋Œ€์ƒ์œผ๋กœ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌ์„ฑํ–ˆ๋‹ค.

์›”๋“œ๋งต
โ†“
๋ชจ๋‹ฅ๋ถˆ ์•„์ด์ฝ˜ ์„ ํƒ
โ†“
๋น ๋ฅธ ์ด๋™ ํ™•์ธ
โ†“
๋กœ๋”ฉ ํ™”๋ฉด ์ถœ๋ ฅ
โ†“
ํ”Œ๋ ˆ์ด์–ด ์ด๋™

๊ธฐ์กด RPG์—์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” OpenLevel ๋ฐฉ์‹ ๋Œ€์‹  ํ˜„์žฌ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ์— ๋งž์ถฐ ํ…”๋ ˆํฌํŠธ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค.

SetActorTransform()

World Partition ํ™˜๊ฒฝ์—์„œ๋Š” ์ด๋™ ์งํ›„ ์…€ ์ŠคํŠธ๋ฆฌ๋ฐ์ด ์™„๋ฃŒ๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ณ ์ • ๋Œ€๊ธฐ ์‹œ๊ฐ„์„ ๋‘์–ด ์ŠคํŠธ๋ฆฌ๋ฐ ์™„๋ฃŒ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋„๋ก ์ฒ˜๋ฆฌํ–ˆ๋‹ค.


UI ๊ตฌ์กฐ ์„ค๊ณ„

๋ชจ๋‹ฅ๋ถˆ UI๋Š” ์ €์žฅ๊ณผ ์ œ์ž‘ ๊ธฐ๋Šฅ์„ ํƒญ ๊ตฌ์กฐ๋กœ ๋ถ„๋ฆฌํ–ˆ๋‹ค.

WBP_BonfireMenu

Save Tab
Craft Tab

๋น ๋ฅธ ์ด๋™์€ ๋ณ„๋„์˜ ๋‹ค์ด์–ผ๋กœ๊ทธ๋ฅผ ์‚ฌ์šฉํ•˜๋„๋ก ๊ตฌ์„ฑํ–ˆ๋‹ค.

WBP_FastTravelDialog
WBP_LoadingCutscene

๋˜ํ•œ ๋น ๋ฅธ ์ด๋™ ๊ณผ์ •์€ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ์—ฐ๊ฒฐํ–ˆ๋‹ค.

OnBonfireIconDoubleClicked
OnFastTravelStarted
OnFastTravelCompleted

UI๊ฐ€ ์ง์ ‘ ๊ฒŒ์ž„ ๋กœ์ง์„ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์ด ์•„๋‹ˆ๋ผ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ๋™์ž‘ํ•˜๋„๋ก ์ •๋ฆฌํ•˜๋ฉด์„œ ์ดํ›„ ์—ฐ์ถœ ์ถ”๊ฐ€๋‚˜ UI ๊ต์ฒด๊ฐ€ ํ›จ์”ฌ ์‰ฌ์›Œ์กŒ๋‹ค.


์˜ค๋Š˜์˜ ์ •๋ฆฌ

  • ์ด๋ฒˆ ์ž‘์—…์„ ํ†ตํ•ด ์ €์žฅ, ์ œ์ž‘, ๋น ๋ฅธ ์ด๋™ ๊ธฐ๋Šฅ์„ ๊ฐœ๋ณ„ ์‹œ์Šคํ…œ์ด ์•„๋‹Œ ํ•˜๋‚˜์˜ RPG ์ง„ํ–‰ ๋ฃจํ”„๋กœ ํ†ตํ•ฉํ–ˆ๋‹ค.
  • SaveGame ๊ตฌ์กฐ๋Š” ์ธ๋ฒคํ† ๋ฆฌ ์ €์žฅ ์ˆ˜์ค€์—์„œ ๋ฒ—์–ด๋‚˜ ์ง„ํ–‰๋„์™€ ์›”๋“œ ์ƒํƒœ ์ €์žฅ๊นŒ์ง€ ํ™•์žฅ ๊ฐ€๋Šฅํ•œ ํ˜•ํƒœ๋กœ ์žฌ์„ค๊ณ„ํ–ˆ๊ณ , ๋ชจ๋‹ฅ๋ถˆ์€ ๋‹จ์ˆœ ์ฒดํฌํฌ์ธํŠธ๊ฐ€ ์•„๋‹Œ ํ”Œ๋ ˆ์ด์–ด ์„ฑ์žฅ๊ณผ ํƒํ—˜์„ ์—ฐ๊ฒฐํ•˜๋Š” ํ•ต์‹ฌ ๊ฑฐ์ ์œผ๋กœ ์—ญํ• ์„ ์ •๋ฆฌํ–ˆ๋‹ค.
  • ๋˜ํ•œ SaveSubsystem, ์›”๋“œ๋งต, ์ œ์ž‘ ์‹œ์Šคํ…œ, UI๋ฅผ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๊ธฐ๋ฐ˜์œผ๋กœ ์—ฐ๊ฒฐํ•˜๋ฉด์„œ ์ดํ›„ ๋ฉ€ํ‹ฐํ”Œ๋ ˆ์ด ์ €์žฅ, ์˜๊ตฌ ์›”๋“œ ์ƒํƒœ, ํŒŒํ‹ฐ ์ด๋™ ๊ธฐ๋Šฅ๊นŒ์ง€ ํ™•์žฅํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋ฐ˜ ๊ตฌ์กฐ๋ฅผ ๋งˆ๋ จํ–ˆ๋‹ค.
profile
๊ฐœ๋ฐœํ•ฉ์‹œ๋‹ค!

0๊ฐœ์˜ ๋Œ“๊ธ€