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
I componenti fabbrica (factory) permettono di generare dinamicamente oggetti di gioco da un pool di oggetti in un gioco in esecuzione.
Quando aggiungi un componente fabbrica a un oggetto di gioco, specifichi nella proprietà Prototype quale file di oggetto di gioco la fabbrica deve usare come prototipo (chiamato anche “prefab” o “blueprint” in altri motori) per tutti i nuovi oggetti di gioco che crea.


Per avviare la creazione di un oggetto di gioco, chiama 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() accetta 5 parametri:
url[position]vector3. Se non specifichi una posizione, l’oggetto di gioco viene generato nella posizione dell’oggetto di gioco che chiama factory.create().[rotation]quat.[properties][scale]number (maggiore di 0) che specifica un ridimensionamento uniforme lungo tutti gli assi. Puoi anche fornire un vector3 in cui ciascuna componente specifica il ridimensionamento lungo l’asse corrispondente.Per esempio:
-- 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 attualmente non supporta il ridimensionamento non uniforme delle forme di collisione. Se fornisci un valore di scala non uniforme, per esempio vmath.vector3(1.0, 2.0, 1.0), lo sprite verrà ridimensionato correttamente, ma le forme di collisione no.
Il meccanismo di indirizzamento di Defold permette di accedere a ogni oggetto e componente in un gioco in esecuzione. Il manuale dell’indirizzamento spiega in dettaglio il funzionamento del sistema. Puoi usare lo stesso meccanismo di indirizzamento per gli oggetti di gioco generati e i loro componenti. Spesso basta usare l’ID dell’oggetto generato, per esempio quando invii un messaggio:
local function create_hunter(target_id)
local id = factory.create("#hunterfactory")
msg.post(id, "hunt", { target = target_id })
return id
end
Inviare un messaggio all’oggetto di gioco stesso invece che a un componente specifico comporta l’invio del messaggio a tutti i componenti. In genere questo non è un problema, ma tienilo presente se l’oggetto ha molti componenti.
Come puoi accedere a un componente specifico di un oggetto di gioco generato, per esempio per disattivare un oggetto di collisione o cambiare l’immagine di uno sprite? La soluzione è costruire un URL a partire dall’ID dell’oggetto di gioco e dall’ID del componente.
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
Quando chiami factory.create(), ottieni l’ID del nuovo oggetto di gioco e puoi memorizzarlo per farvi riferimento in seguito. Un uso comune consiste nel generare oggetti e aggiungere i loro ID a una tabella per poterli eliminare tutti in un secondo momento, per esempio quando ripristini la disposizione degli oggetti di un livello:
-- 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)
E poi, in un secondo momento:
-- 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)
Spesso serve anche che l’oggetto generato conosca l’oggetto di gioco che lo ha generato. Un esempio è un tipo di oggetto autonomo di cui può esistere una sola istanza generata alla volta. L’oggetto generato deve quindi avvisare il generatore quando viene eliminato o disattivato, in modo che se ne possa generare un altro:
-- 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
E la logica dell’oggetto generato:
-- drone.script
go.property("parent", msg.url())
...
function final(self)
-- I'm dead.
msg.post(self.parent, "drone_dead")
end
Selezionando la casella Load Dynamically nelle proprietà della fabbrica, il motore rimanda il caricamento delle risorse associate alla fabbrica.

Con la casella deselezionata, il motore carica le risorse del prototipo quando viene caricato il componente fabbrica, rendendole subito disponibili per generare oggetti.
Con la casella selezionata, hai due possibilità:
factory.create() quando vuoi generare oggetti. Le risorse verranno caricate in modo sincrono, il che potrebbe causare un breve rallentamento, e poi verranno generate nuove istanze.
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() per caricare esplicitamente le risorse in modo asincrono. Quando le risorse sono pronte per generare oggetti, viene invocata una callback.
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
Puoi cambiare il Prototype che una fabbrica può creare selezionando la casella Dynamic Prototype nelle proprietà della fabbrica.

Quando l’opzione Dynamic Prototype è selezionata, il componente fabbrica può cambiare prototipo usando la funzione factory.set_prototype(). Esempio:
factory.unload("#factory") -- unload the previous resources
factory.set_prototype("#factory", "/main/levels/enemyA.goc")
local enemy_id = factory.create("#factory")
Quando l’opzione Dynamic Prototype è attiva, il numero di componenti della collezione non può essere ottimizzato e la collezione che contiene la fabbrica userà i conteggi predefiniti dei componenti del file game.project.
L’impostazione di progetto Max Instances nella sezione Collection è il limite massimo al numero di oggetti di gioco in ciascuna collezione (mondo). Durante la build, Defold può allocare una capacità inferiore quando può stabilire che ciò è sicuro. Tutti gli oggetti di gioco che esistono contemporaneamente in un mondo concorrono al raggiungimento della capacità, sia che siano stati inseriti nell’editor sia che siano stati generati durante l’esecuzione.

L’allocazione effettiva dipende dall’analisi svolta durante la build:
Imposta Max Instances in base al maggior numero di oggetti di gioco che possono esistere contemporaneamente in un mondo dinamico. Consulta Ottimizzazioni del numero massimo di componenti per sapere come vengono calcolati gli altri limiti dei componenti.
Può sembrare una buona idea conservare gli oggetti di gioco generati in un pool e riutilizzarli. Tuttavia, il motore gestisce già internamente un pool di oggetti, quindi il lavoro aggiuntivo causerebbe solo rallentamenti. Eliminare gli oggetti di gioco e generarne di nuovi è più veloce e più semplice.