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
Les composants factory (factory component) servent à créer dynamiquement des objets de jeu (game object) à partir d’une réserve d’objets dans un jeu en cours d’exécution.
Lorsque vous ajoutez un composant factory à un objet de jeu, vous indiquez dans la propriété Prototype le fichier d’objet de jeu que la factory doit utiliser comme prototype (également appelé « prefabs » ou « blueprints » dans d’autres moteurs) pour tous les nouveaux objets de jeu qu’elle crée.


Pour déclencher la création d’un objet de jeu, appelez factory.create() :
-- factory.script
local p = go.get_position()
p.y = vmath.lerp(math.random(), min_y, max_y)
local component = "#star_factory"
factory.create(component, p)

factory.create() prend cinq paramètres :
url[position]vector3. Si vous n’indiquez pas de position, l’objet de jeu est créé à la position de l’objet de jeu qui appelle factory.create().[rotation]quat.[properties][scale]number (supérieur à 0) qui définit une mise à l’échelle uniforme sur tous les axes. Vous pouvez également fournir un vector3 dont chaque composante définit la mise à l’échelle sur l’axe correspondant.Par exemple :
-- factory.script
local p = go.get_position()
p.y = vmath.lerp(math.random(), min_y, max_y)
local component = "#star_factory"
-- Spawn with no rotation but double scale.
-- Set the score of the star to 10.
factory.create(component, p, nil, { score = 10 }, 2.0) -- <1>
-- star.script
go.property("score", 1) -- <1>
local speed = -240
function update(self, dt)
local p = go.get_position()
p.x = p.x + speed * dt
if p.x < -32 then
go.delete()
end
go.set_position(p)
end
function on_message(self, message_id, message, sender)
if message_id == hash("collision_response") then
msg.post("main#gui", "add_score", {amount = self.score}) -- <2>
go.delete()
end
end

Defold ne prend actuellement pas en charge la mise à l’échelle non uniforme des formes de collision. Si vous fournissez une valeur d’échelle non uniforme, par exemple vmath.vector3(1.0, 2.0, 1.0), le sprite sera mis à l’échelle correctement, mais pas les formes de collision.
Le mécanisme d’adressage de Defold permet d’accéder à chaque objet et composant dans un jeu en cours d’exécution. Le manuel sur l’adressage explique en détail le fonctionnement de ce système. Vous pouvez utiliser le même mécanisme d’adressage pour les objets de jeu créés dynamiquement et leurs composants. Il suffit souvent d’utiliser l’identifiant de l’objet créé, par exemple pour envoyer un message :
local function create_hunter(target_id)
local id = factory.create("#hunterfactory")
msg.post(id, "hunt", { target = target_id })
return id
end
Envoyer un message à l’objet de jeu lui-même plutôt qu’à un composant particulier transmet en fait le message à tous les composants. Cela ne pose généralement pas de problème, mais gardez-le à l’esprit si l’objet possède de nombreux composants.
Mais comment accéder à un composant particulier d’un objet de jeu créé dynamiquement, par exemple pour désactiver un objet de collision ou changer l’image d’un sprite ? La solution consiste à construire une URL à partir de l’identifiant de l’objet de jeu et de celui du composant.
local function create_guard(unarmed)
local id = factory.create("#guardfactory")
if unarmed then
local weapon_sprite_url = msg.url(nil, id, "weapon")
msg.post(weapon_sprite_url, "disable")
local body_sprite_url = msg.url(nil, id, "body")
sprite.play_flipbook(body_sprite_url, hash("red_guard"))
end
end
Lorsque vous appelez factory.create(), vous obtenez l’identifiant du nouvel objet de jeu, que vous pouvez conserver pour l’utiliser ultérieurement. Un usage courant consiste à créer des objets et à ajouter leurs identifiants à une table afin de pouvoir tous les supprimer plus tard, par exemple lors de la réinitialisation de l’agencement d’un niveau :
-- spawner.script
self.spawned_coins = {}
...
-- Spawn a coin and store it in the "coins" table.
local id = factory.create("#coinfactory", coin_position)
table.insert(self.spawned_coins, id)
Puis, plus tard :
-- spawner.script
-- Delete all spawned coins.
for _, coin_id in ipairs(self.spawned_coins) do
go.delete(coin_id)
end
-- or alternatively
go.delete(self.spawned_coins)
Il est également courant de vouloir que l’objet créé connaisse l’objet de jeu qui l’a créé. C’est le cas, par exemple, d’un type d’objet autonome dont une seule instance peut être créée à la fois. L’objet créé doit alors informer son créateur lorsqu’il est supprimé ou désactivé, afin qu’un autre puisse être créé :
-- spawner.script
-- Spawn a drone and set its parent to the url of this script component
self.spawned_drone = factory.create("#dronefactory", drone_position, nil, { parent = msg.url() })
...
function on_message(self, message_id, message, sender)
if message_id == hash("drone_dead") then
self.spawned_drone = nil
end
end
Et la logique de l’objet créé :
-- drone.script
go.property("parent", msg.url())
...
function final(self)
-- I'm dead.
msg.post(self.parent, "drone_dead")
end
Si vous cochez la case Load Dynamically dans les propriétés de la factory, le moteur reporte le chargement des ressources qui lui sont associées.

Lorsque la case est décochée, le moteur charge les ressources du prototype au moment du chargement du composant factory, afin qu’elles soient immédiatement prêtes pour la création d’objets.
Lorsque la case est cochée, vous avez deux possibilités :
factory.create() lorsque vous souhaitez créer des objets. Les ressources seront chargées de manière synchrone, ce qui peut provoquer une brève interruption, puis de nouvelles instances seront créées.
function init(self)
-- No factory resources are loaded when the factory’s parent
-- collection is loaded. Calling create without having called
-- load will create the resources synchronously.
self.go_id = factory.create("#factory")
end
function final(self)
-- Delete game objects. Will decref resources.
-- In this case resources are deleted since the factory component
-- holds no reference.
go.delete(self.go_id)
-- Calling unload will do nothing since factory holds no references
factory.unload("#factory")
end
factory.load() pour charger explicitement les ressources de manière asynchrone. Lorsqu’elles sont prêtes pour la création d’objets, une fonction de rappel (callback) est appelée.
function load_complete(self, url, result)
-- Loading is complete, resources are ready to spawn
self.go_id = factory.create(url)
end
function init(self)
-- No factory resources are loaded when the factory’s parent
-- collection is loaded. Calling load will load the resources.
factory.load("#factory", load_complete)
end
function final(self)
-- Delete game object. Will decref resources.
-- In this case resources aren’t deleted since the factory component
-- still holds a reference.
go.delete(self.go_id)
-- Calling unload will decref resources held by the factory component,
-- resulting in resources being destroyed.
factory.unload("#factory")
end
Vous pouvez changer le Prototype qu’une factory peut créer en cochant la case Dynamic Prototype dans les propriétés de la factory.

Lorsque l’option Dynamic Prototype est cochée, le composant factory peut changer de prototype à l’aide de la fonction factory.set_prototype(). Exemple :
factory.unload("#factory") -- unload the previous resources
factory.set_prototype("#factory", "/main/levels/enemyA.goc")
local enemy_id = factory.create("#factory")
Lorsque l’option Dynamic Prototype est activée, le nombre de composants de la collection ne peut pas être optimisé, et la collection qui contient la factory utilisera les nombres de composants par défaut du fichier game.project.
Le paramètre de projet Max Instances, dans la section Collection, définit la limite supérieure du nombre d’objets de jeu dans chaque collection (monde). Lors du build, Defold peut allouer une capacité plus faible s’il peut déterminer que cela ne présente aucun risque. Tous les objets de jeu présents simultanément dans un monde sont comptabilisés dans cette capacité, qu’ils aient été placés dans l’éditeur ou créés à l’exécution.

L’allocation effective dépend de l’analyse effectuée lors du build :
Définissez Max Instances en fonction du plus grand nombre d’objets de jeu susceptibles d’être présents simultanément dans un monde dynamique. Consultez la section Optimisations des nombres maximaux de composants pour savoir comment les autres limites de composants sont calculées.
Il peut sembler judicieux de conserver les objets de jeu créés dans une réserve pour les réutiliser. Cependant, le moteur gère déjà une réserve d’objets en interne, et toute surcharge supplémentaire ne fera que ralentir les opérations. Il est à la fois plus rapide et plus propre de supprimer les objets de jeu et d’en créer de nouveaux.