Collection proxy - kuimoani/defold GitHub Wiki
Collection Proxies
Defold๋ ์ปฌ๋ ์ ์ ๋ชจ๋ ๊ฒ์ ์ค๋ธ์ ํธ๋ฅผ ๊ตฌ์ฑํฉ๋๋ค. ์ด ๋งค๋ด์ผ์ ๊ฒ์ ์คํ์ค์ ๋์ ์ผ๋ก ์ปฌ๋ ์ ์ ๋ก๋ํ๊ณ ์ธ๋ก๋ํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์ค๋ช ํฉ๋๋ค.
์ปฌ๋ ์ ์๋ ๊ฒ์ ์ค๋ธ์ ํธ๋ฅผ ์ถ๊ฐํ ์ ์์ผ๋ฉฐ, ์ฌ์ง์ด ๋ค๋ฅธ ์ปฌ๋ ์ ์ ์ถ๊ฐ ํ ์๋ ์์ต๋๋ค(์: ์๋ธ-์ปฌ๋ ์ ). Defold๊ฐ ์คํ๋๋ฉด project settings์ ์ ์๋ ์ต์์ ์ปฌ๋ ์ (top level collection)์ด ๋ก๋(loads), ๊ฐ์(initiates), ํ์ฑํ(enables) ๋๋ฉฐ, ๋๋ถ๋ถ ํ๋ก์ ํธ ์์ฑ์ ๊ฒ์ ์คํ ์ฆ์ ์ฒ์์ผ๋ก ์คํ๋๋ "main.collection"๋ ํจ๊ป ์์ฑ๋ฉ๋๋ค.
๋๋ค์ ํ๋ก์ ํธ์์๋, ์ต์์ ์ปฌ๋ ์ ์๋ง ์ ์ฒด ์ฑ์ ํฌํจํ๋ ๊ฒ์ผ๋ก ์ถฉ๋ถํ์ง๋ง, ํ๋ก์ ํธ๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํด ๋ ๊ฐ๋ ฅํ ๋ฐฉ๋ฒ์ผ๋ก ์ฌ๋ฌ ์ต์์ ์ปฌ๋ ์ ๋ค์ ๋์ ์ผ๋ก ๋ก๋ฉํ๊ณ ์ธ๋ก๋ฉ ํ๋ ์ฌ๋ฌ ์์ (์๋ ์ฐธ๊ณ )๊ฐ ์์ต๋๋ค.
์ปฌ๋ ์ ํ๋ก์(Collection proxy)๋ ์ปฌ๋ ์ ํ์ผ ๋์ ์ฌ์ฉ๋๋ ์ฐฝ๊ตฌ ์ญํ ์ ํ๋ฉฐ, ์ด ํ๋ก์๋ฅผ ์ด์ฉํ์ฌ ์์ง ๋ก๋๋์ง ์์ ์ปฌ๋ ์ ํ์ผ๊ณผ load, initialize, enable, disable, finalize, unload์ ์ปค๋ฎค๋์ผ์ด์ ์ ํ ์ ์์ต๋๋ค.
๋ก๋ฉ๊ณผ ์ธ๋ก๋ฉ์ ๊ด๋ จ๋ ์ปฌ๋ ์ ํ๋ก์๋ฅผ ์ฌ์ฉํ๋ ๋ชจ๋ ์ปค๋ฎค๋์ผ์ด์ ์ ๋น๋๊ธฐ์ (asynchronously)์ผ๋ก ์ํ๋์ง๋ง, ์ค์ ๋ก ๋ก๋ฉ๊ณผ ์ธ๋ก๋ฑ์ด ๋ฐฑ๊ทธ๋ผ์ด๋ ํ๋ก์ธ์ค์์ ๊ตฌํ๋๋ ๊ฒ์ ์๋๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก ์์ง์ด ์ค์ ๋ก๋ฉ์ด๋ ์ธ๋ก๋ฉ์ ๋ฐ์ํ๋ฉด ์งง๊ฒ ์ค์ง(pause)๋ ๊ฒ์ ๋๋ค.
Typical use cases
๋ง์ ๊ฒ์๋ค์ ๋์ด๋ ์์๋๋ก ํ๋ ์ด ํ ์ ์๊ฒ ์ฌ๋ฌ ๋ ๋ฒจ๋ก ๋๋์ด์ ธ ์์ต๋๋ค. ๋ง์ฝ ๋ ๋ฒจ ์ปจํ ์ธ ๊ฐ ๊ทธ๋ฅ ์๋ํฐ์์์ ์๋์ผ๋ก ๊ตฌ์ฑ๋ ๊ฒฝ์ฐ, ๋ ๋ฒจ ์์ ์์๋ค(ํ์ผ๋งต, ์คํ๋ผ์ดํธ ๋ฑ)์ ๊ทธ์ ์ปฌ๋ ์ ๋ชจ์์ผ๋ก ๋๋๋ฒ๋ฆด ๊ฒ์ ๋๋ค. ์ปฌ๋ ์ ํ๋ก์๋ ์ด ์ปจํ ์ธ ๋ค์ ๋ถ๋ฆฌํ๊ณ ์คํฌ๋ฆฝํธ๋ฅผ ํตํด ๋์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์๊ฒ ํด ์ค๋๋ค.
์๋๋ ์ปฌ๋ ์ ํ๋ก์(collection proxy)์ ์์์ ๋๋ค.
- ๊ฒ์ ๋ ๋ฒจ์ Loading/unloading
- GUI ํ๋ก ํธ์๋์ Loading/unloading
- ๊ฒ์ ๋ ๋ฒจ์ ์คํ ๋ฆฌ ๊ฐ์๊ฑธ ๋ณด์ฌ์ฃผ๋ ์ฌ(scene)์ Loading/unloading
- ๋ฏธ๋๊ฒ์์ Loading/unloading
- ์ฌ์ฉ์๊ฐ ์ ํํ ์ปจํ ์ธ (์์ , ๋ฐฐ๊ฒฝ์ด๋ฏธ์ง ๋ฑ)์ Loading/unloading
ํฐ ์ฌ๋ฆฌ์ค ์๋์์ "streaming" ์ง์ญ์ ๋ก๋ฉ/์ธ๋ก๋ฉ ํ๋ ๊ฒ์ ์ปฌ๋ ์ ํ๋ก์๋ฅผ ํ์ฉํ์ฌ ๊ตฌํ ๊ฐ๋ฅํฉ๋๋ค. ํ์ง๋ง ์ค์ ๋ก๋ฉ์ ๋๊ธฐ์(๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋์ํ์ง ์๊ณ , ๋ก๋ฉ์ด ์๋ฃ๋ ๋๊น์ง ๊ฒ์์ ์ค๋จํ๋๊ฒ์ ์๋ฏธํจ)์ผ๋ก ์ํ๋๋ฉฐ ๋ก๋ฉ ์๊ฐ์ ์ฌ๋ฌ ํ๋ ์์ด ๊ฑธ๋ฆด ์ ์์ต๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก ์๋์ ์กฐ๊ฐ์ ์๊ฒ ์ ์งํ๊ฑฐ๋ ๋ก๋ฉ์ผ๋ก ์ธํ ๋ฉ์ถค์ ์ด๋ป๊ฒ๋ ์จ๊ธฐ๋ ๋ฐฉ๋ฒ์ ์ฐพ์์ผ ํฉ๋๋ค.
Worlds
์ปฌ๋ ์ ํ๋ก์๋ฅผ ํตํ๋ฉด ์ต์์ ์ปฌ๋ ์ ์ ์ ํํ๊ฑฐ๋ ํ ๊ฐ ์ด์์ ์ต์์ ์ปฌ๋ ์ ์ ๊ฒ์ ์์ง์ ๋ก๋ํ๋ ๊ฒ์ด ๊ฐ๋ฅํฉ๋๋ค. ๋จ, ๊ฐ ์ต์์ ์ปฌ๋ ์ ์ ๋ถ๋ฆฌ๋ ๋ฌผ๋ฆฌ ์๋์ด๋ฉฐ ๋ฌผ๋ฆฌ ์ํธ์์ฉ(Physics interactions: collisions, triggers, ray-casts)์ ๋์ผํ ์ปฌ๋ ์ ์ ์์๋ ์ค๋ธ์ ํธ ๋ผ๋ฆฌ๋ง ๋ฐ์ํ๋ค๋ ๊ฒ์ ์์ ๋ฌ์ผ ํฉ๋๋ค. ์ฆ, ๊ฐ๊ธฐ ๋ค๋ฅธ ์ต์์ ์ปฌ๋ ์ ์ ์์๋ ์ค๋ธ์ ํธ๋ค ์ฌ์ด์์๋ ๋ฌผ๋ฆฌ ์ํธ์์ฉ์ด ๋ฐ์ํ์ง ์์ต๋๋ค.
์๋ ์์ ์์๋ ๊ฒ์ ์๋๋ฅผ ์ปฌ๋ ์ ํ๋ก์๋ฅผ ํตํด ๋์ ์ผ๋ก ๋ก๋๋๋ ๋ ๊ฐ์ ์ปฌ๋ ์ ์ผ๋ก ๋ถํ ํ์ต๋๋ค. ๋ ์ปฌ๋ ์ ์ ๋ก๋ ๋ฐ ์ธ๋ก๋๋ "loader"๋ผ๋ ๊ฒ์ ์ค๋ธ์ ํธ์ ์ํด ์ ์ด๋๋ฉฐ ์ด ์ค๋ธ์ ํธ๋ ๋ฉ์ธ ์ปฌ๋ ์ ์ธ "worlds"์ ๋ค์ด ์์ต๋๋ค. ๊ฒ์์ด ์์๋ ๋ "worlds.collection" ํ์ผ์ ์๋์ผ๋ก ๋ก๋ํ๋๋ก ๊ตฌ์ฑ(Project settings ์ฐธ๊ณ )ํฉ๋๋ค. "world" ์ปฌ๋ ์ ์ "loader" ์ค๋ธ์ ํธ ๋ฟ๋ง์๋๋ผ ์ฐ๋ฆฌ๊ฐ ์บ๋ฆญํฐ๋ฅผ ์์ง์ผ ์ ์๊ฒ ํด์ฃผ๋ GUI ์์๋ ํฌํจํ๊ณ ์์ต๋๋ค.

์ฒซ๋ฒ์งธ ์ปฌ๋ ์ "world1"์ ์ผํธ์ ๋ณด๋ผ์ ๋ฐ๋ฅ์ ํ์ผ์ด ์์ต๋๋ค. ์ค๋ฅธํธ์ "exit" ํ์งํ๊ณผ ๋ น์ ๋ฐ๋ฅ ํ์ผ์ "world2" ์ปฌ๋ ์ ์ ๋๋ค.

์ฐ๋ฆฌ์ ํ๋ ์ด์ด ์บ๋ฆญํฐ๋ ๋ ๋ฒจ์ ๋ชจ๋ ๋ฐ๋ฅ ํ์ผ์ ๋ํด ๋ฌผ๋ฆฌ ์ถฉ๋์ด ์ ํ ๋์ด ์์ผ๋ฉฐ ํ๋ ์ด์ด๊ฐ ๋ฐ๋ฅ ์์ ์บ๋ฆญํฐ๋ฅผ ๋ฐ๊ตด๋ฐ๊ตด ๊ตด๋ฆด ์ ์๊ฒ ํด ์ค๋๋ค. ํ์ง๋ง ํ๋ ์ด์ด๊ฐ "world1" ์ปฌ๋ ์ ์ ๋์ ๋ฟ์ผ๋ฉด ์ด๋ค ์ผ์ด ์ผ์ด๋๋์ง ๋ด ์๋ค.

"world2"์ ํ์ผ์ "world1"๊ณผ ์์ ํ ๋์ผํ๊ฒ ์ถฉ๋ ์ ํ ์ด ๋์ด ์์ง๋ง, "world1" ์ ์์๋ ํ๋ ์ด์ด ์บ๋ฆญํฐ ๊ฒ์ ์ค๋ธ์ ํธ๋ ์ถฉ๋์ด ๋ฐ์ํ์ง ์๊ณ ์บ๋ฆญํฐ๊ฐ ๊ทธ๋ฅ ์๋๋ก ๋ ๋จ์ด์ ธ ๋ฒ๋ฆฝ๋๋ค.
๋ง์ฝ ๋ชจ๋ ๋ ๋ฒจ๋ค์ด ํ ์ปฌ๋ ์ ๋ด์ ์ ๋ถ ํฌํจ๋์ด ์๊ณ , ํ๋ ์ด์ด๊ฐ ์ด๋ค ๋ ๋ฒจ ์ฌ์ด๋ฅผ ์ํํ๊ฒ(seamlessly) ์ด๋ํ์ง ๋ชปํ ๊ฒ์ผ๋ก ์์๋๋ ๊ฒ์์์๋, ์ด๋ฌํ ์ปฌ๋ ์ ์ ํน์ฑ ๋๋ฌธ์ ์๋๋ฅผ ๋ถ๋ฆฌํ๋๋ฐ ์ฌ์ฉ๋๊ธฐ ์ด๋ ต์ต๋๋ค.
๋์ค์ ์ด ์์ ๋ฅผ ์์ธํ ์ดํด๋ณด๊ณ ๊ฒ์์ด ๋ฌผ๋ฆฌ ์ถฉ๋, ํธ๋ฆฌ๊ฑฐ๋ฅผ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์ง, ํ๋ ์ด์ด๊ฐ ์ด๋ํ ์ ์๋ ๊ฒ์์๋ ์กฐ๊ฐ์ ๋์ ์ผ๋ก ์ด๋ป๊ฒ ๋ก๋ํ๋์ง๋ ์ดํด ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค. ํ์ง๋ง ์ฐ์ ์ปฌ๋ ์ ํ๋ก์์ ๊ธฐ์ด๋ถํฐ ์ดํด ๋ณด๋๋ก ํฉ์๋ค.
Editing
์ปฌ๋ ์ ํ๋ก์๋ฅผ ์ค์ ํ๊ธฐ ์ํด์๋, ๊ฒ์ ์ค๋ธ์ ํธ์ ์ปฌ๋ ์ ํ๋ก์ ์ปดํฌ๋ํธ๋ฅผ ์ถ๊ฐํ๊ณ ํ๋ก์์ ์ด๋ฆ์ ์ ํ๊ณ (id ์ง์ ) ์ด๋ค ์ปฌ๋ ์ ํ์ผ์ด ์ด๋ฅผ ๋์ ํ์ฌ ์๋ํ ์ง ์ง์ ํ๋ฉด ๋ฉ๋๋ค.

Naming collections
์ปฌ๋ ์ ํ๋ก์์ ์ปค๋ฎค๋์ผ์ด์ ์ ์์ํ๊ธฐ ์ ์, ๊ฐ ์ปฌ๋ ์ ๋ค์ ์ด๋ฆ์ ํ์ธ ํด์ผ ํฉ๋๋ค. ์๋ํฐ์์ ์์ฑํ ๊ฐ ์ปฌ๋ ์ ์ "default"๋ผ๋ ์ด๋ฆ์ผ๋ก ์๋ ํ ๋น ๋ฉ๋๋ค. ํ๋ก์๋ฅผ ํตํด ์ปฌ๋ ์ ์ ๋์ ์ผ๋ก ๋ก๋ํ์ง ์๋ ํ, ์ด ์ด๋ฆ์ ์ ์งํ ์ ์์ต๋๋ค.

ํ์ง๋ง ์ปฌ๋ ์ ํ๋ก์๋ฅผ ํตํด ๋ ๊ฐ ์ด์์ ์ต์์ ๋ ๋ฒจ ์ปฌ๋ ์ ์ ๋ก๋ํ๋ ๊ฒฝ์ฐ, ๊ฐ ์ปฌ๋ ์ ์ URL์ ์์ผ ๋ถ๋ถ์ ํตํด ์ฃผ์๊ฐ ์ง์ ๋์ด์ผ ํ๊ณ , ์ด ์์ผ ์ด๋ฆ์ ๋ฐ๋์ ์ ๋ํฌํด์ผ๋ง ํฉ๋๋ค.
msg.post("world1:manager#script", "remove_player")
msg.post("world2:manager#script", "spawn_player")
๊ทธ๋ฌ๋ฏ๋ก ํ๋ก์๋ฅผ ํตํด ๋ก๋ํ๋ ค๋ ์ปฌ๋ ์ ์ ์ ๋ํฌํ ์ด๋ฆ์ผ๋ก ์์ ํ๋๊ฒ์ด ์ข์ต๋๋ค. ๋ง์ฝ ์ ๋ํฌํ ์ด๋ฆ์ ์ง์ ํ์ง ์์ผ๋ฉด ์์ง์ ์ด๋ฆ ์ถฉ๋ ์๋ฌ๋ฅผ ๋ฐ์ํฉ๋๋ค.
ERROR:GAMEOBJECT: The collection 'default' could not be created since there is already a socket with the same name.
WARNING:RESOURCE: Unable to create resource: build/default/worlds/world1.collectionc
ERROR:GAMESYS: The collection /worlds/world1.collectionc could not be loaded.
Loading
ํ๋ก์๋ฅผ ํตํด ์ปฌ๋ ์ ์ ๋ก๋ํ๋ ค๋ฉด "load" ๋ฉ์ธ์ง๋ฅผ ๊ฒ์ ์ค๋ธ์ ํธ์ ํ๋ก์ ์ปดํฌ๋ํธ์๊ฒ ์ ์กํ๋ฉด ๋ฉ๋๋ค.
-- "world1" ํ๋ก์์๊ฒ ๋ก๋ฉ ์์ํ๋ผ๊ณ ์๋ ค์ค
msg.post("loader#world1", "load")
ํ๋ก์๊ฐ ๋ก๋ฉ์ ๋๋ด๋ฉด "proxy_loaded" ๋ฉ์ธ์ง๋ฅผ ๋๋๋ ค ์ค๋๋ค. ์ด ๋ฉ์ธ์ง๋ฅผ ๋ฐ์์ ์ปฌ๋ ์ ์ ์ด๊ธฐํ(initialize) ํ๊ณ ํ์ฑํ(enable) ํ ์ ์์ต๋๋ค.
function on_message(self, message_id, message, sender)
if message_id == hash("proxy_loaded") then
-- ๋ด ์๋๊ฐ ๋ก๋๋์๋ค. Init๊ณผ enable ํ์
msg.post(sender, "init")
msg.post(sender, "enable")
...
์๋๋ฉด ๋ฉ์ธ์ง์ ์ถ์ฒ๋ฅผ ์ฒดํฌํด์ ๊ทธ์ ๋ง๋ ์ฒ๋ฆฌ๋ฅผ ํ๊ฒ ํ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค. "proxy_loaded" ๋ฅผ ๋ณด๋ธ ์ปฌ๋ ์ ํ๋ก์๋ sender URL์ ํ๋๊ทธ๋จผํธ ๋ถ๋ถ(fragment part)์ ํ์๋ฉ๋๋ค.
function on_message(self, message_id, message, sender)
if message_id == hash("proxy_loaded") and sender.fragment == hash("myproxy1") then
-- "myproxy1"๊ฐ ๋ก๋๋๋ฉด init ํ๊ณ enable ํ์...
...
"init" ๋ฉ์ธ์ง๋ก ํ๋ก์๋ฅผ ํตํด ์ปฌ๋ ์ ์ ์ด๊ธฐํ(Initializing) ํ๋ ๊ฒ์ ์ปฌ๋ ์ ์ ํฌํจ๋ ๋ชจ๋ ์ค๋ธ์ ํธ๋ค์ ์ฌ๊ท์ ์ผ๋ก(recursively) ์ด๊ธฐํ ํฉ๋๋ค. "enable" ๋ฉ์ธ์ง๋ก ํ๋ก์๋ฅผ ํตํด ์ปฌ๋ ์ ์ ํ์ฑํ(Enabling)ํ๋ ๊ฒ๋ ์ปฌ๋ ์ ์ ํฌํจ๋ ๋ชจ๋ ์ค๋ธ์ ํธ๋ค์ ์ฌ๊ท์ ์ผ๋ก ํ์ฑํ ํ๊ฒ ๋ฉ๋๋ค.
(์ค๋ธ์ ํธ์ ์๋ช ์ฃผ๊ธฐ์ ๋ํด ์์ธํ ๋ณด๊ณ ์ถ๋ค๋ฉด Application lifecycle ์ฐธ๊ณ )
"enable"์ ๋ก๋๋ ํ๋ก์์๊ฒ ๋ณด๋ด๋ฉด enable์ ์ํํ๊ธฐ ์ ์ ์ปฌ๋ ์ ์ ์๋์ผ๋ก ์ด๊ธฐํ(init) ํฉ๋๋ค. ๊ทธ๋ฌ๋ฏ๋ก ์ด๊ธฐํ์ ํ์ฑํ ๋จ๊ณ ๋ณ๋ก ์ธ๋ถํ ๋ ์ ์ด๊ฐ ํ์ํ๊ฒ ์๋๋ผ๋ฉด ๊ทธ๋ฅ ์๋์ฒ๋ผ ์จ๋ ๋ฉ๋๋ค.
-- ๋ด ์๋๊ฐ ๋ก๋๋์๋ค. Init๊ณผ enable ํ์
msg.post(sender, "enable")
๋ค์ ํ๋ซํฌ๋จธ ์์ ๋ก ๋์์์, "world1" ์ปฌ๋ ์ ์ ํธ๋ฆฌ๊ฑฐ๋ฅผ ํ๋ ๋ฃ๊ณ "world2"๋ฅผ ๋ก๋ํ ์์น์ ๋ฐฐ์น ํ๋๋ก ํฉ๋๋ค.

์ฐ๋ฆฌ๋ "worldswitch"๋ผ๋ ๊ฒ์ ์ค๋ธ์ ํธ์ ์ ํ ๋ก์ง(switching logic)์ด ํฌํจ๋ ํธ๋ฆฌ๊ฑฐ๋ฅผ ๋ง๋ค๊ณ , ์ค๋ธ์ ํธ๋ฅผ ์ฌ์ฌ์ฉ ํ ์ ์๊ฒ ํด ์ฃผ๋ ๋ ํ๋กํผํฐ๋ฅผ ๋ฌถ์ต๋๋ค. ์ด ํ๋กํผํฐ๋ ํด์ฌ ํ์์ด๋ฏ๋ก ํ๋ก์๋ค์ด ์ปค๋ฎค๋์ผ์ด์ ํ ์ ์๋๋ก URL์ ๊ตฌ์ฑํด์ผ ํฉ๋๋ค. ์ฐ๋ฆฌ๋ "loader" ๊ฒ์ ์ค๋ธ์ ํธ๊ฐ ์ถ๊ฐ๋ "worlds" ์ปฌ๋ ์ ์ ์ด ๋ฉ์ธ์ง๋ค๋ฅผ ๋ณด๋ผ ๊ณํ์ ๋๋ค.
go.property("selfworld", hash(""))
go.property("otherworld", hash(""))
function init(self)
-- ํ๋ก์๋ค์ ์ํ url ๊ตฌ์ฑํ๊ธฐ... ๋์ค์ ์ฌ์ฉํ ์์ ์
self.selfurl = msg.url()
self.selfurl.socket = "worlds"
self.selfurl.path = hash("/loader")
self.selfurl.fragment = self.selfworld
self.otherurl = msg.url()
self.otherurl.socket = "worlds"
self.otherurl.path = hash("/loader")
self.otherurl.fragment = self.otherworld
end
์ฌ๊ธฐ์๋ "world2" ์ปฌ๋ ์ ์ ์ ํ ํฉ๋๋ค.

"exit" ํ์งํ์ ๋ ์ปฌ๋ ์ ์์ ์์ ํ ๋์ผํ ์ขํ์ ๋ฐฐ์นํด์ ํ๋์ ํ์ผ๋ก ๊ฒน์ณ ๋ณด์ด๊ฒ ํฉ๋๋ค. ๋ํ "world1" ๋ฟ๋ง ์๋๋ผ "world2" ์๋ "player" ์ค๋ธ์ ํธ๊ฐ ํ์ ํฉ๋๋ค. ๊ฐ ์ปฌ๋ ์ ์ ๊ฐ์ ์์ฒด์ ๋ฌผ๋ฆฌ ์ธ๊ณ(physics world)๋ฅผ ๊ฐ์ง๊ณ ์๊ธฐ ๋๋ฌธ์ ํ๋ ์ด์ด ๋ํ ๋ณ๋๋ก ์์ด์ผ ํ๋ฉฐ ์๋ ์ฌ์ด๋ฅผ ๋์ด ๊ฐ ๋ ์ ๋ ฅ ์ ์ด(input control)์ ํฌ์ง์ ์ ํ ์ชฝ ํ๋ ์ด์ด์์ ๋ค๋ฅธ ์ชฝ ํ๋ ์ด์ด๋ก ๋๊ธธ ๊ฒ์ ๋๋ค.
๊ทธ๋ฌ๋ฏ๋ก ํ๋ ์ด์ด๊ฐ "world1"์ ํธ๋ฆฌ๊ฑฐ์ ์ถฉ๋ํ๋ฉด, ์ฐ๋ฆฌ๋ "world2" ๋ก๋ฉ์ ์์ํ๋ฉด ๋ฉ๋๋ค.
function on_message(self, message_id, message, sender)
if message_id == hash("trigger_response") and message.enter then
-- ํ๋ ์ด์ด๊ฐ ์๋ ์ ํ ํธ๋ฆฌ๊ฑฐ์ ์ถฉ๋ํจ
-- ์์ ์ ๊ตฌ์ฑํด ๋์ url์ ํตํด ์ฐธ์กฐ๋ ๋ค์ ์๋ ๋ถ๋ฌ์ค๊ธฐ
msg.post(self.url, "load")
...
๋ค์์ผ๋ก๋, ๋ก๋ ์์ ์ด ์๋ฃ๋๋ฉด ์ปฌ๋ ์ ์ ํ์ฑํ ํฉ๋๋ค.
elseif message_id == hash("proxy_loaded") then
-- ์ ์๋๊ฐ ๋ก๋ ๋์์ผ๋ Enable ํ์
msg.post(sender, "enable")
์ด์ ๋ ํ๋ ์ด์ด ์ค๋ธ์ ํธ๋ฅผ ์ ํ ์ํฌ ๋์ ๋๋ค. ์ฐ๋ฆฌ๋ ํ์ฌ ํ๋ ์ด์ด์๊ฒ ํ์ฌ ํฌ์ง์ ๋ฑ๋ฑ์ ํ์ํ ๋ฐ์ดํฐ๋ฅผ ์๊ตฌํ๋ ๋ฉ์ธ์ง๋ฅผ ์ ์กํด์ ํ๋ ์ด์ด ์ ํ ์์ ์ ์์ํฉ๋๋ค.
-- ํ๋ ์ด์ด์ ์์น๋ฅผ ๋ค๋ฅธ ์๋์ ํ๋ ์ด์ด์๊ฒ ์ ์กํด์ผํจ
local currentsocket = ""
-- ํด์ฌ๋ ํ๋กํผํฐ๋ ๋ฌธ์์ด๋ก ๋ง๋ค ์ ์์ผ๋ฏ๋ก ์ด๋ ๊ฒ ํด์ผํจ
if self.selfworld == hash("world1") then
currentsocket = "world1"
elseif self.selfworld == hash("world2") then
currentsocket = "world2"
end
msg.post(currentsocket .. ":" .. "/player#script", "request_player")
์ฌ๊ธฐ์๋ "player_response" ๋ฉ์ธ์ง๋ฅผ ๋ฐ์์ ์๋ก ๋ก๋๋ ์ปฌ๋ ์ ์ ํ๋ ์ด์ด์๊ฒ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด ์ค๋๋ค.
elseif message_id == hash("player_response") then
-- ํ๋ ์ด์ด ํฌ์ง์
๊ฐ์ ๋๋ ค ๋ฐ์์..
-- ๋ค๋ฅธ ์๋์ ํ๋ ์ด์ด์๊ฒ ๋ฐ์ํด์ผ ํจ
local othersocket = ""
if self.otherworld == hash("world1") then
othersocket = "world1"
elseif self.otherworld == hash("world2") then
othersocket = "world2"
end
-- ๋ฐ์ ๋ฉ์ธ์ง๋ฅผ ๊ฑ ๋๊น
msg.post(othersocket .. ":" .. "/player#script", "inherit_player", message)
end
"inherit_player" ๋ฉ์ธ์ง๋ ์ ์กํ ํฌ์ง์ ์ ์์ํ๋ฏ๋ก ์ ํ๋ ์ด์ด๋ ์ด์ ํ๋ ์ด์ด์ ๋์ผํ ์์น๋ก ์ฌ๋ฐฐ์น ๋ฉ๋๋ค. (์ฌ๊ธฐ์, ์๋ก ๋ค๋ฅธ ์ปฌ๋ ์ ์ ์๊ณ ๋ฌผ๋ฆฌ ์ธ๊ณ๋ ๊ตฌ๋ถ๋๋ฏ๋ก ์ ํ๋ ์ด์ด๋ ํธ๋ฆฌ๊ฑฐ ์ถฉ๋์ด ๊ฐ์ง๋์ง ์์ต๋๋ค.)
์ด์ ๊ฒ์์ ์คํํ๋ฉด "world1"์์ "world2"๋ก ์ด๋ํ ์ ์์ง๋ง "world1"์ ํ๋ ์ด์ด ์ค๋ธ์ ํธ๊ฐ ์์ง๋ ์กด์ฌํ๊ณ ์๊ณ "world2"์ ์๋๋ก ๋์ด๊ฐ๋ฉด ๋ ๋จ์ด์ง๊ฒ ๋ฉ๋๋ค.

๊ทธ๋ฌ๋ ์ด์ ์ฐ๋ฆฌ๋ "world2"์ ํ๋ ์ด์ด๋ฅผ ์ ์ดํ ์ ์๊ณ ์ ๋ ๋ฒจ๋ก ์บ๋ฆญํฐ๋ฅผ ๊ตด๋ฆด ์ ์์ต๋๋ค.

Unloading
์ด์ ์ฐ๋ฆฌ๋ ์๋ ์ ํ ๋ก์ง์ ์กฐ๊ธ ์ ๋ฆฌํ๊ธฐ๋ง ํ๋ฉด ๋ฉ๋๋ค. ์ค๋ช ์ ์ํด์ ์ฐ๋ฆฌ๊ฐ ๋จ๊ฒจ๋ ์ปฌ๋ ์ ์ ๊ฐ๋จํ๊ฒ ์ธ๋ก๋ ํด๋ณด๊ฒ ์ต๋๋ค. ํ์ง๋ง ์ฐ์ , ์ธ๋ก๋๊ฐ ์ด๋ป๊ฒ ๋์ํ๋์ง ๋ถํฐ ์ดํด๋ด ์๋ค.
์ธ๋ก๋ฉ์ ๋ก๋ฉ๋์๋ ๋ฐ๋ ์์๋ก ์ฒ๋ฆฌํฉ๋๋ค.
msg.post("loader#world1", "disable")
msg.post("loader#world1", "final")
msg.post("loader#world1", "unload")
"disable" ๋ฉ์ธ์ง๋ก ํ๋ก์๋ฅผ ํตํด ์ปฌ๋ ์ ์ ๋นํ์ฑํ(Disabling) ํ๋ ๊ฒ์ ์ปฌ๋ ์ ์ ํฌํจ๋ ๋ชจ๋ ์ค๋ธ์ ํธ๋ค์ ์ฌ๊ท์ ์ผ๋ก(recursively) ๋นํ์ฑํ ํฉ๋๋ค. "final" ๋ฉ์ธ์ง๋ก ํ๋ก์๋ฅผ ํตํด ์ปฌ๋ ์ ์ ๋ง๋ฌด๋ฆฌ(Finalizing)ํ๋ ๊ฒ๋ ์ปฌ๋ ์ ์ ํฌํจ๋ ๋ชจ๋ ์ค๋ธ์ ํธ๋ค์ ์ฌ๊ท์ ์ผ๋ก ๋ง๋ฌด๋ฆฌ ํ๊ฒ ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ "unload" ๋ฉ์ธ์ง๋ ์ปฌ๋ ์ ์ ๋ฉ๋ชจ๋ฆฌ์์ ์ญ์ ํฉ๋๋ค.
ํ๋ก์๊ฐ ์ปฌ๋ ์ ์ ์ธ๋ก๋ํ๋ฉด "proxy_unloaded" ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ด์ค๋๋ค.
if message_id == hash("unload_level") then
local proxy = msg.url("#proxy")
msg.post(proxy, "disable")
msg.post(proxy, "final")
msg.post(proxy, "unload")
elseif message_id == hash("proxy_unloaded") then
-- Ok, ๋ ๋ฒจ์ด ์ธ๋ก๋ ๋์๊ตฌ๋ง
...
์ธ์ธํ ์ปจํธ๋กค์ด ํ์ํ๊ฒ ์๋๋ผ๋ฉด, ์ปฌ๋ ์ ์ disable, final ํ์ง ์๊ณ ๊ทธ๋ฅ "unload" ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ด๋ ๋ฉ๋๋ค. ํ๋ก์๊ฐ unload ๋๊ธฐ ์ ์ ์ปฌ๋ ์ ์ ์๋์ ์ผ๋ก disableํ๊ณ finalize ํฉ๋๋ค.
์ด์ ๋ค์ ์ฐ๋ฆฌ์ ํ๋ซํฌ๋จธ ์์ ๋ก ๋์์์, ์ฐ๋ฆฌ๊ฐ ํด์ผ ํ ๋จ์ ์ผ์ ์ฌ๋ฐ๋ฅธ ํ๋ก์๋ก ์ด ๋ฉ์ธ์ง๋ค์ ๋ณด๋ด๋ ๊ฒ ๋ฟ์ ๋๋ค. ์ฐ๋ฆฌ๋ ๋ฐ์ดํฐ ์์ฒญ์ ์ํ "request_player" ๋ฉ์ธ์ง๋ฅผ ์ ํ๋ ์ด์ด ์ค๋ธ์ ํธ์๊ฒ ๋ณด๋ธ ์ดํ์ ์ธ๋ก๋ ์์ ์ ์ํํฉ๋๋ค.
...
msg.post(currentsocket .. ":" .. "/player#script", "request_player")
-- ์ด์ ๋จ๊ฒจ์ง ์๋๋ฅผ ๋ฒ๋ฆด ๋๊ฐ ๋์์
-- ํ๋ฉด์ ๋ค ๋ณด์ด๋๋ฐ์ ์ญ์ ํด๋ฒ๋ฆฌ๋๊ฒ ์ด์ํ๊ฒ ๋ณด์ด์ง๋ง, ์๋ ์๋ฆฌ ์ดํด๋ฅผ ์ํด ๊ฑ ์ญ์ ํจ
msg.post(self.selfurl, "disable")
msg.post(self.selfurl, "final")
msg.post(self.selfurl, "unload")
์ด์ ์ผ์ชฝ์ ์ปฌ๋ ์ ์ ํ๋ ์ด์ด๋ฅผ ๋ค๋ก ํ๊ณ ์ธ๋ก๋ ๋๊ฒ ๋ฉ๋๋ค.

์ค์ ๊ฒ์์์๋ผ๋ฉด ํ๋ฉด์ ๋ณด์ด๋ ์ํ์์๋ ์ปฌ๋ ์ ์ ์ธ๋ก๋ํ์ง ์๋๊ฒ ์ข์ต๋๋ค. ๋ง์ฝ ํ๋ ์ด์ด์ ์ ํ(switching)์ ๋์ฑ ๋ถ๋๋ฝ๊ฒ ๋ง๋ค๊ณ ์ถ๋ค๋ฉด, ํ๋ ์ด์ด ์ปจํธ๋กค์ ๋ฐ๋ฅธ ๊ฐ์๋(momentum)์ ํ๋ ์ด์ด์ ์ ๋๋ฉ์ด์ ์ํ(animation state)๋ฅผ ์์ ๋ฐ์ ์ฒ๋ฆฌํ๊ฑฐ๋ ์ ํ ์ง์ ์ ํน์ ํจ๊ณผ ๊ฐ์๊ฑฐ๋ก ๊ฐ๋ ค ๋ฒ๋ฆฌ๋ ๊ฒ๋ ์ข์ ๋ฐฉ๋ฒ์ ๋๋ค. ์ด ์ฌํํ ์์ ๋ ๋จ์ง ์ด์ ํ๋ ์ด์ด์ ํฌ์ง์ ๋ง ์์ํ ๋ฟ์ด๋ผ ๊ฐ๋(angular)์ ์ ํ ์๋(linear velocity)๊ฐ 0์ผ๋ก ์ค์ ๋ฉ๋๋ค.
Input
๋ง์ฝ ๋ก๋๋ ์ปฌ๋ ์ ์์ ์ธํ ์ก์ (input action)์ด ํ์ํ ์ค๋ธ์ ํธ๊ฐ ์๋ค๋ฉด, ์ปฌ๋ ์ ํ๋ก์๋ฅผ ํฌํจํ๊ณ ์๋ ๊ฒ์ ์ค๋ธ์ ํธ๊ฐ ์ ๋ ฅ์ ํ๋(acquire)ํ๋์ง ํ์ธํ ํ์๊ฐ ์์ต๋๋ค. ๊ฒ์ ์ค๋ธ์ ํธ๊ฐ ์ ๋ ฅ ๋ฉ์ธ์ง๋ฅผ ์์ ํ๋ฉด, ์ด๋ค์ ์ค๋ธ์ ํธ์ ์ปดํฌ๋ํธ, ์ฆ ์ปฌ๋ ์ ํ๋ก์๋ค์๊ฒ ์ ํ(propagated)๋ฉ๋๋ค. ์ธํ ์ก์ ์ ๋ก๋๋ ์ปฌ๋ ์ ์๊ฒ ํ๋ก์๋ฅผ ํตํด์ ์ ๋ฌ๋๊ฒ ๋ฉ๋๋ค.

"world1"์ด๋ "world2"์ ์์๋ ์ค๋ธ์ ํธ์์ ์ธํ์ก์ ์ ๋ฐ๊ธฐ ์ํ๋ค๋ฉด, ๊ฐ๋จํ๊ฒ "loader" ๊ฒ์์ค๋ธ์ ํธ์ ์คํฌ๋ฆฝํธ์์ ์ธํ ํฌ์ปค์ค(input focus)๋ฅผ ํ๋ํ๋ฉด ๋ฉ๋๋ค.
function init(self)
-- ์
๋ ฅ์ ํ๋ํด์ ์ปฌ๋ ์
์ค๋ธ์ ํธ๋ค์ด ์
๋ ฅ์ ๋ฐ์๊ฑฐ์
msg.post(".", "acquire_input_focus")
...
์ด์ "world1" ๋๋ "world2"์ ์ค๋ธ์ ํธ๊ฐ "acquire_input_focus" ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ด์ ์ธํ ์ก์ ์ ๋ฐ์ ์ ์์ต๋๋ค. (์ ๋ ฅ์ ๋ํ ์์ธํ ์ ๋ณด๋ Input์ ์ฐธ๊ณ ํ์ธ์.)
Time step
๊ฐ ์ปฌ๋ ์ ํ๋ก์๋ ์ดํ๋ฆฌ์ผ์ด์ ์ ์ ๋ฐ์ดํธ ์ฃผ๊ธฐ์ ๊ด๋ จ๋ ํ์์คํ (time step)์ ์ ๋ฐ์ดํธ ํ๋๊ฒ์ ๊ฐ๋ณ์ ์ผ๋ก ์ ์ดํ ์ ์์ต๋๋ค. ๊ธ๋ก๋ฒ ์ ๋ฐ์ดํธ ์ฃผ๊ธฐ(global update frequency)๋ ์ดํ๋ฆฌ์ผ์ด์ ํ๋ก์ ํธ ์ ํ (์ด๋น 60 ํ๋ ์ ์ ๋ฐ์ดํธ๋ฅผ ๊ธฐ๋ณธ๊ฐ์ผ๋ก ํจ)์์ ์ค์ ํ๊ฑฐ๋ @system ์์ผ์ผ๋ก ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ด์ ์ค์ ํ ์๋ ์์ต๋๋ค.
msg.post("@system:", "set_update_frequency", { frequency = 60 } )
์ปฌ๋ ์ ํ๋ก์์ ์ ๋ฐ์ดํธ๋ time step์ ๋ณ๊ฒฝํด์ ์ค์ผ์ผ(scale) ํ ์ ์์ต๋๋ค. ์ฆ ๊ฒ์ ํฑ(tick)์ด ๊พธ์คํ๊ฒ 60FPS ๋ผ๋, ํ๋ก์๋ ๋ ๋๊ฑฐ๋ ๋ ๋ฎ์ ํ์ด์ค(pace)๋ก ์ ๋ฐ์ดํธ ํ ์ ์์ผ๋ฉฐ, ๋ฌผ๋ฆฌ ์์คํ ๊ณผ update() ํจ์์ ๋๊ฒจ์ฃผ๋ "dt" ๋ณ์์ ์ํฅ์ ๋ฏธ์น๊ฒ ๋ฉ๋๋ค. ๋ํ ์ ๋ฐ์ดํธ ๋ชจ๋(update mode)๋ฅผ ์ค์ ํ์ฌ ์ค์ผ์ผ๋ง์ด ๋ถ์ฐ์์ ์ผ๋ก(discretely) ์ํ๋์ด์ผ ํ๋์ง(1.0 ์ดํ์ ์ค์ผ์ผ ํํฐ(scale factor)์์๋ง ์๋ฏธ๊ฐ ์์) ์ฐ์์ ์ผ๋ก(continuously) ์ํ๋์ด์ผ ํ๋์ง๋ฅผ ์ ์ดํ ์ ์๊ฒ ํด ์ค๋๋ค.
ํ๋ก์์ "set_time_step" ๋ฉ์ธ์ง๋ฅผ ๋ณด๋ด์ ์ค์ผ์ผ ํํฐ(scale factor)์ ์ค์ผ์ผ๋ง ๋ชจ๋(scaling mode)๋ฅผ ์ ์ดํ ์ ์์ต๋๋ค.
-- ํ๋ก์ ์ปฌ๋ ์
์ 1/5 ์๋๋ก ์
๋ฐ์ดํธ ํจ
msg.post("#proxy", "set_time_step", {factor = 0.2, mode = 1}
time step์ ๋ณ๊ฒฝํ๋ฉด ๋ฌด์จ ์ผ์ด ๋ฐ์ํ๋์ง ๋ณด๋ ค๋ฉด, ์ค๋ธ์ ํธ๋ฅผ ๋ง๋ค์ด ์คํฌ๋ฆฝํธ ์ปดํฌ๋ํธ์ ์๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๊ณ timestep์ ๋ณ๊ฒฝํ๋ ค๋ ์ปฌ๋ ์ ์ ๋ฃ์ผ๋ฉด ๋ฉ๋๋ค.
function update(self, dt)
print("update() with timestep (dt) " .. dt)
end
time step์ 0.2๋ก ์ค์ ํ๊ธฐ ๋๋ฌธ์, ์ฝ์์ฐฝ์์ ์๋์ ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ์ถ๋ ฅ๋ฉ๋๋ค.
INFO:DLIB: SSDP started (ssdp://192.168.0.102:54967, http://0.0.0.0:62162)
INFO:ENGINE: Defold Engine 1.2.37 (6b3ae27)
INFO:ENGINE: Loading data from: build/default
DEBUG:SCRIPT: update() with timestep (dt) 0
DEBUG:SCRIPT: update() with timestep (dt) 0
DEBUG:SCRIPT: update() with timestep (dt) 0
DEBUG:SCRIPT: update() with timestep (dt) 0
DEBUG:SCRIPT: update() with timestep (dt) 0.016666667535901
DEBUG:SCRIPT: update() with timestep (dt) 0
DEBUG:SCRIPT: update() with timestep (dt) 0
DEBUG:SCRIPT: update() with timestep (dt) 0
DEBUG:SCRIPT: update() with timestep (dt) 0
DEBUG:SCRIPT: update() with timestep (dt) 0.016666667535901
update() ๋ ์ฌ์ ํ ์ด๋น 60๋ฒ ํธ์ถ ๋์ง๋ง "dt"๊ฐ์ ๋ฐ๋๊ฒ ๋ฉ๋๋ค. update()๋ฅผ ํธ์ถํ๋ 1/5 (0.2) ๋ง์ด 1/60 (60fps)์ ํด๋นํ๋ "dt"๋ฅผ ๊ฐ์ง๊ฒ ๋๋ฉฐ, ๋๋จธ์ง๋ 0์ด ๋ฉ๋๋ค. ๋ํ ๋ชจ๋ ๋ฌผ๋ฆฌ ์๋ฎฌ๋ ์ด์ ์ dt์ ๋ฐ๋ผ ์ ๋ฐ์ดํธ ๋๋ฉฐ ์ค์ง ํ๋ ์ ๋น 1/5๋ง ์งํ๋ฉ๋๋ค.
์์ธํ ๋ด์ฉ์ set_time_step ๋ฅผ ์ฐธ๊ณ ๋ฐ๋๋๋ค.
(์ผ๋ถ ๊ทธ๋ํฝ ์์ ์ Kenney์ ์ํด ์ ์๋์์ต๋๋ค : http://kenney.nl/assets)