Компонент Collection Factory используется для порождения групп и иерархий игровых объектов, хранящихся в файлах коллекций, в запущенной игре.
В Defold коллекции обеспечивают эффективный способ создания многократно используемых шаблонов, или “префабов”. Обзор коллекций см. в документации по структурным элементам. Коллекции можно создавать в редакторе или вставлять в игру динамически.
С помощью фабрик коллекций можно порождать содержимое файла коллекции в игровой мир. Это аналогично выполнению порождения фабрикой всех игровых объектов внутри коллекции с последующим построением иерархии “родительский-дочерний” между объектами. Типичным примером является порождение врагов, состоящих из нескольких игровых объектов (например, враг + оружие).
Предположим, нам нужен игровой объект персонаж и отдельный игровой объект щит, дочерний по отношению к персонажу. Мы построим иерархию игровых объектов в файле коллекции и сохраним его под именем “bean.collection”.
Компонент collection proxy используется для создания нового игрового мира, включая отдельный физический мир, на основе коллекции. Доступ к новому миру осуществляется через новый сокет. Все ассеты, содержащиеся в коллекции, загружаются через прокси, когда вы сообщаете прокси о начале загрузки. Это делает их очень полезными, например, для изменения уровней в игре. Однако новые игровые миры сопровождаются довольно большими накладными расходами, поэтому не стоит использовать их для динамической загрузки мелкого контента. За подробностями обращайтесь к документации по прокси-коллекциям.
Затем добавляется Collection factory к игровому объекту, который будет осуществлять порождение, и устанавливается “bean.collection” в качестве прототипа компонента:
Теперь порождение объектов “bean” и “shield” — это просто вызов функции collectionfactory.create()
:
local bean_ids = collectionfactory.create("#bean_factory")
Функция принимает 5 параметров:
url
[position]
vector3
. Если не указать позицию, объекты будут порождены в позиции фабрики.[rotation]
quat
.[properties]
id
-table
, используемая для инициирования порожденных игровых объектов. Как построить эту таблицу, смотрите ниже.[scale]
number
(больше 0), которое задает равномерное масштабирование по всем осям. Можно также указать vector3
, где каждый компонент задает масштабирование по соответствующей оси.collectionfactory.create()
возвращает идентификаторы порожденных игровых объектов в виде таблицы. Ключи таблицы отображают хэш локального идентификатора коллекции каждого объекта на идентификатор каждого объекта в среде выполнения:
Отношение “родительский-дочерний” между “bean” и “shield” не отражается в возвращаемой таблице. Это отношение существует только в графе сцены среды выполнения, то есть в том, как объекты преобразуются вместе. Повторное подчинение объекта никогда не изменяет его id.
local bean_ids = collectionfactory.create("#bean_factory")
go.set_scale(0.5, bean_ids[hash("/bean")])
pprint(bean_ids)
-- DEBUG:SCRIPT:
-- {
-- hash: [/shield] = hash: [/collection0/shield], -- <1>
-- hash: [/bean] = hash: [/collection0/bean],
-- }
/collection[N]/
, где [N]
— счетчик, добавляемый к id для уникальной идентификации каждого экземпляра:При порождении коллекции можно передать свойства каждому игровому объекту, построив таблицу, где ключами являются идентификаторы объектов, а значениями — таблицы со свойствами скрипта, которые нужно установить.
local props = {}
props[hash("/bean")] = { shield = false }
local ids = collectionfactory.create("#bean_factory", nil, nil, props)
Предположим, что игровой объект “bean” в “bean.collection” определяет свойство “shield”. Руководство по свойствам скрипта содержит информацию о свойствах сценария.
-- bean/controller.script
go.property("shield", true)
function init(self)
if not self.shield then
go.delete("shield")
end
end
Отметив в свойствах фабрики коллекций Load Dynamically, движок откладывает загрузку ресурсов, связанных с фабрикой.
Если опция не отмечена, движок загружает ресурсы прототипа при загрузке компонента фабрики коллекций, так что они сразу готовы к порождению.
Если опция отмечена, есть два варианта использования:
collectionfactory.create()
, когда нужно породить объекты. При этом ресурсы будут загружены синхронно, что может вызвать заминку, а затем будут порождены новые экземпляры.
function init(self)
-- No factory resources are loaded when the collection factory’s
-- parent collection is loaded. Calling create without
-- having called load will create the resources synchronously.
self.go_ids = collecionfactory.create("#collectionfactory")
end
function final(self)
-- Delete game objects. Will decref resources.
-- In this case resources are deleted since the collection
-- factory component holds no reference.
go.delete(self.go_ids)
-- Calling unload will do nothing since factory holds
-- no references
collectionfactory.unload("#factory")
end
collectionfactory.load()
для явной асинхронной загрузки ресурсов. Когда ресурсы будут готовы к порождению, будет получен обратный вызов.
function load_complete(self, url, result)
-- Loading is complete, resources are ready to spawn
self.go_ids = collectionfactory.create(url)
end
function init(self)
-- No factory resources are loaded when the collection factory’s
-- parent collection is loaded. Calling load will load the resources.
collectionfactory.load("#factory", load_complete)
end
function final(self)
-- Delete game object. Will decref resources.
-- In this case resources aren’t deleted since the collection factory
-- component still holds a reference.
go.delete(self.go_ids)
-- Calling unload will decref resources held by the factory component,
-- resulting in resources being destroyed.
collectionfactory.unload("#factory")
end
Did you spot an error or do you have a suggestion? Please let us know on GitHub!
GITHUB