This translation is community contributed and may not be up to date. We only maintain the English version of the documentation. Read this manual in English
コレクションプロキシ(collection proxy)コンポーネント(component)は、コレクション(collection)ファイルの内容に基づいて、新しい「ゲームワールド」(game world)を動的に読み込み、アンロード(読み込んだデータの解放)するために使います。ゲームのレベルや GUI 画面の切り替え、レベル内での物語の「シーン」の読み込みとアンロード、ミニゲームの読み込みとアンロードなどを実装できます。
Defold はすべてのゲームオブジェクト(game object)をコレクションにまとめます。コレクションには、ゲームオブジェクトやほかのコレクション(サブコレクション)を含めることができます。コレクションプロキシを使うと、コンテンツを個別のコレクションに分割し、スクリプトでそれらの読み込みとアンロードを動的に管理できます。
コレクションプロキシは、コレクションファクトリー(collection factory)コンポーネントとは異なります。コレクションファクトリーは、コレクションの内容を現在のゲームワールドにインスタンス化します。コレクションプロキシは実行時に新しいゲームワールドを作成するため、用途が異なります。
ゲームオブジェクトを 右クリック し、コンテキストメニューから Add Component ▸ Collection Proxy を選択して、ゲームオブジェクトにコレクションプロキシコンポーネントを追加します。
Collection プロパティに、あとでランタイムに動的に読み込むコレクションを指定します。これはビルド時の静的な依存関係です。参照したコレクションとその依存リソースはコンパイルされます。Exclude にチェックを入れない限り、それらはメインバンドルに含まれます。Exclude にチェックを入れると、除外したプロキシからのみ参照されるリソースを Live Update 用にメインバンドルから省略できます。また、後述する方法で、読み込まれていないプロキシの参照先を実行時に別のコンパイル済みコレクションへ変更できます。

(Exclude チェックボックスにチェックを入れ、Live Update 機能を使うと、コンテンツをビルドから除外し、代わりにコードでダウンロードできます。)
Defold エンジンが起動すると、起動時に読み込まれる ブートストラップコレクション(bootstrap collection) からすべてのゲームオブジェクトをランタイムに読み込み、インスタンス化します。その後、ゲームオブジェクトとそのコンポーネントを初期化して有効にします。エンジンが使うブートストラップコレクションは、プロジェクト設定で指定します。慣例として、このコレクションファイルには通常 main.collection という名前を付けます。

ゲームオブジェクトとそのコンポーネントを格納するため、エンジンは、ブートストラップコレクションの内容がインスタンス化される「ゲームワールド」全体に必要なメモリを割り当てます。衝突判定や物理特性を持つコンポーネントであるコリジョンオブジェクト(collision object)と物理シミュレーションのために、個別の物理ワールド(physics world)も作成されます。
スクリプトコンポーネントは、ブートストラップのワールドの外側からでもゲーム内のすべてのオブジェクトをアドレス指定できる必要があります。そのため、このワールドには一意の名前が付けられます。その名前は、コレクションファイルで設定する Name プロパティです。

読み込まれるコレクションにコレクションプロキシコンポーネントが含まれている場合、それらが参照するコレクションは自動的には読み込まれません。これらのリソースの読み込みは、スクリプトで制御する必要があります。
プロキシ経由でコレクションを動的に読み込むには、スクリプトからプロキシコンポーネントに "load" というメッセージを送信します。
-- Tell the proxy "myproxy" to start loading.
msg.post("#myproxy", "load")

プロキシコンポーネントは、新しいワールドのための領域を割り当てるようエンジンに指示します。個別のランタイム物理ワールドも作成され、「mylevel.collection」コレクション内のすべてのゲームオブジェクトがインスタンス化されます。
新しいワールドの名前には、コレクションファイルの Name プロパティが使われます。この例では「mylevel」に設定されています。名前は一意である必要があります。コレクションファイルで設定した Name が、読み込み済みのワールドですでに使われていると、エンジンは名前の衝突エラーを出力します。
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/mylevel.collectionc
ERROR:GAMESYS: The collection /mylevel.collectionc could not be loaded.
エンジンがコレクションの読み込みを完了すると、コレクションプロキシコンポーネントは、"load" メッセージを送信したスクリプトに "proxy_loaded" というメッセージを返します。スクリプトは、このメッセージに応じてコレクションを初期化し、有効にできます。
function on_message(self, message_id, message, sender)
if message_id == hash("proxy_loaded") then
-- New world is loaded. Init and enable it.
msg.post(sender, "init")
msg.post(sender, "enable")
...
end
end
"load""proxy_loaded" というメッセージを返します。"async_load""proxy_loaded" というメッセージを返します。"init"init() 関数が呼び出されます。"enable"collectionproxy.set_collection() を使うと、除外されていて読み込まれていないプロキシの参照先を、コンパイル済みコレクションへ変更できます。これは、Live Update パッケージをマウントしたあとに役立ちます。プロキシは Exclude にチェックが入っている必要があり、読み込み済みでも読み込み中でもあってはいけません。パスの末尾は .collectionc である必要があります。プロキシを読み込むときには、コレクションとそのすべての依存リソースがリソースシステムで利用できる必要があります。
プロキシを読み込む前に戻り値を確認してください。新しいワールドの初期化と有効化は、proxy_loaded を受信してから行ってください。
local function load_mounted_level()
local ok, result = collectionproxy.set_collection(
"#level_proxy",
"/level_pack/level_3.collectionc"
)
if ok then
msg.post("#level_proxy", "load")
else
print("Unable to change proxy collection", result)
end
end
function on_message(self, message_id, message, sender)
if message_id == hash("proxy_loaded") then
msg.post(sender, "init")
msg.post(sender, "enable")
end
end
エディターで割り当てたコレクションに戻すには、プロキシが読み込み済みでも読み込み中でもない状態で collectionproxy.set_collection("#level_proxy", nil) を呼び出します。コンテンツのダウンロードとマウントについては Live Update スクリプティングマニュアルを、collectionproxy.RESULT_* の失敗コードについては API リファレンスを参照してください。
コレクションファイルのプロパティで設定した Name は、読み込まれたワールド内のゲームオブジェクトとコンポーネントのアドレス指定に使われます。たとえば、ブートストラップコレクションにローダーオブジェクトを作成した場合、読み込まれた任意のコレクションからそのオブジェクトと通信する必要があるかもしれません。
-- tell the loader to load the next level:
msg.post("main:/loader#script", "load_level", { level_id = 2 })

ローダーから、読み込まれたコレクション内のゲームオブジェクトと通信する必要がある場合は、オブジェクトへの完全な URL を使ってメッセージを送信できます。
msg.post("mylevel:/myobject", "hello")
読み込まれたコレクション内のゲームオブジェクトには、コレクションの外側から直接アクセスできません。
local position = go.get_position("mylevel:/myobject")
-- loader.script:42: function called can only access instances within the same collection.
読み込んだコレクションをアンロードするには、読み込みとは逆の手順に対応するメッセージを送信します。
-- unload the level
msg.post("#myproxy", "disable")
msg.post("#myproxy", "final")
msg.post("#myproxy", "unload")
"disable""final"final() 関数が呼び出されます。"unload"細かな制御が必要なければ、コレクションを先に無効にしたり終了処理を行ったりせずに、"unload" メッセージを直接送信できます。その場合、プロキシはコレクションをアンロードする前に、自動的に無効にして終了処理を行います。
コレクションプロキシがコレクションのアンロードを完了すると、"unload" メッセージを送信したスクリプトに "proxy_unloaded" メッセージを返します。
function on_message(self, message_id, message, sender)
if message_id == hash("proxy_unloaded") then
-- Ok, the world is unloaded...
...
end
end
コレクションプロキシの更新速度は、更新やシミュレーションの時間刻みである タイムステップ(time step) を変更することで調整できます。つまり、ゲームが一定の 60 FPS で進んでいても、プロキシはより速い、または遅いペースで更新でき、次のようなものに影響します。
update() に渡される dt更新モードも設定できます。これにより、速度の調整を離散的に行うか(スケール係数が 1.0 未満の場合にのみ意味があります)、連続的に行うかを制御できます。
プロキシに set_time_step メッセージを送信して、スケール係数と調整モードを制御します。
-- update loaded world at one-fifth-speed.
msg.post("#myproxy", "set_time_step", {factor = 0.2, mode = 1}
タイムステップを変更すると何が起こるかを確認するため、スクリプトコンポーネントに次のコードを持つオブジェクトを作成し、タイムステップを変更するコレクションに配置します。
function update(self, dt)
print("update() with timestep (dt) " .. dt)
end
タイムステップを 0.2 にすると、コンソールに次の結果が表示されます。
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() は引き続き1秒あたり60回呼び出されますが、dt の値が変わります。update() の呼び出しのうち、dt が 1/60(60 FPS に相当)になるのは 1/5(0.2)だけで、残りはゼロです。すべての物理シミュレーションもこの dt に従って更新され、5フレームに1回だけ進みます。
コレクションのタイムステップ機能を使うと、たとえばポップアップを表示している間や、ウィンドウがフォーカスを失ったときに、ゲームを一時停止できます。一時停止するには msg.post("#myproxy", "set_time_step", {factor = 0, mode = 0}) を、再開するには msg.post("#myproxy", "set_time_step", {factor = 1, mode = 1}) を使います。
詳細は set_time_step を参照してください。