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
Компонент (component) проксі колекції (collection proxy) використовується для динамічного завантаження й вивантаження нових ігрових «світів» на основі вмісту файлу колекції (collection). За допомогою проксі колекцій можна реалізувати перемикання між ігровими рівнями й екранами GUI, завантаження та вивантаження сюжетних «сцен» у межах рівня, завантаження й вивантаження мініігор тощо.
Defold організовує всі ігрові об’єкти (game object) у колекції. Колекція може містити ігрові об’єкти та інші колекції (тобто підколекції). Проксі колекцій дають змогу розділити вміст на окремі колекції, а потім динамічно керувати їхнім завантаженням і вивантаженням за допомогою скриптів.
Проксі колекцій відрізняються від компонентів фабрики колекцій (collection factory). Фабрика колекцій створює екземпляри (instance) вмісту колекції в поточному ігровому світі. Проксі колекцій створюють новий ігровий світ під час виконання, тому мають інші сфери застосування.
Додайте компонент проксі колекції до ігрового об’єкта: клацніть правою кнопкою миші ігровий об’єкт і виберіть Add Component ▸ Collection Proxy у контекстному меню.
Установіть властивість Collection так, щоб вона посилалася на колекцію, яку ви хочете згодом динамічно завантажити в середовище виконання. Це статична залежність на етапі збирання: колекція, на яку вказує посилання, та її залежності компілюються. Якщо прапорець Exclude не встановлено, вони включаються до основного пакета. Коли прапорець Exclude встановлено, ресурси, на які посилаються лише виключені проксі, можна не включати до основного пакета для Live Update, а незавантажений проксі можна перенаправити на іншу скомпільовану колекцію під час виконання, як описано нижче.

(Ви можете виключити вміст зі збірки й натомість завантажити його за допомогою коду, встановивши прапорець Exclude та скориставшись функцією Live Update.)
Під час запуску рушій Defold завантажує та створює в середовищі виконання екземпляри всіх ігрових об’єктів зі стартової колекції (bootstrap collection). Потім він ініціалізує й вмикає ігрові об’єкти та їхні компоненти. Стартова колекція, яку має використовувати рушій, задається в налаштуваннях проєкту. За усталеною домовленістю цей файл колекції зазвичай має назву main.collection.

Щоб розмістити ігрові об’єкти та їхні компоненти, рушій виділяє пам’ять, потрібну для всього «ігрового світу», у якому створюються екземпляри вмісту стартової колекції. Також створюється окремий фізичний світ для всіх об’єктів колізій і фізичної симуляції.
Оскільки компоненти-скрипти повинні мати змогу адресувати всі об’єкти в грі, навіть з-поза світу стартової колекції, цьому світу надається унікальне ім’я — значення властивості 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.
Коли рушій завершить завантаження колекції, компонент проксі колекції надішле повідомлення "proxy_loaded" у відповідь скрипту, що надіслав повідомлення "load". У відповідь на це повідомлення скрипт може ініціалізувати й увімкнути колекцію:
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" безпосередньо, не вимикаючи й не фіналізуючи колекцію заздалегідь. Тоді проксі автоматично вимкне та фіналізує колекцію перед її вивантаженням.
Коли проксі колекції завершить вивантаження колекції, він надішле повідомлення "proxy_unloaded" у відповідь скрипту, що надіслав повідомлення "unload":
function on_message(self, message_id, message, sender)
if message_id == hash("proxy_unloaded") then
-- Ok, the world is unloaded...
...
end
end
Швидкість оновлення проксі колекції можна масштабувати, змінюючи крок часу. Це означає, що навіть якщо гра працює зі сталою частотою 60 FPS, проксі може оновлюватися швидше або повільніше, впливаючи на такі речі:
dt, передане до update()Ви також можете задати режим оновлення, щоб керувати тим, чи масштабування виконується дискретно (що має сенс лише за коефіцієнта масштабування меншого за 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() усе ще викликається 60 разів на секунду, але значення dt змінюється. Бачимо, що лише 1/5 (0.2) викликів update() матиме dt, рівне 1/60 (що відповідає 60 FPS), — в інших викликах воно дорівнює нулю. Усі фізичні симуляції також оновлюватимуться відповідно до цього dt і просуватимуться лише в кожному п’ятому кадрі.
Ви можете скористатися кроком часу колекції, щоб призупинити гру, наприклад, під час показу спливного вікна або коли вікно втратило фокус. Використовуйте msg.post("#myproxy", "set_time_step", {factor = 0, mode = 0}), щоб призупинити гру, і msg.post("#myproxy", "set_time_step", {factor = 1, mode = 1}), щоб продовжити.
Докладніше дивіться set_time_step.