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
Eine Fabrik (factory) ist eine Komponente (component), die Spielobjekte (game objects) aus einem Objektpool dynamisch in einem laufenden Spiel erzeugt.
Wenn du einem Spielobjekt eine Fabrikkomponente hinzufügst, legst du in der Eigenschaft Prototype fest, welche Spielobjektdatei die Fabrik als Prototyp (in anderen Engines auch als „Prefabs“ oder „Blueprints“ bekannt) für alle neuen Spielobjekte verwenden soll, die sie erzeugt.


Rufe factory.create() auf, um die Erzeugung eines Spielobjekts auszulösen:
-- 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() nimmt 5 Parameter entgegen:
url[position]vector3 angegeben werden. Wenn du keine Position angibst, wird das Spielobjekt an der Position des Spielobjekts erzeugt, das factory.create() aufruft.[rotation]quat angegeben werden.[properties][scale]number (größer als 0) angegeben werden, der eine gleichmäßige Skalierung entlang aller Achsen festlegt. Du kannst auch einen vector3 angeben, bei dem jede Komponente die Skalierung entlang der entsprechenden Achse festlegt.Zum Beispiel:
-- 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 unterstützt derzeit keine ungleichmäßige Skalierung von Kollisionsformen. Wenn du einen ungleichmäßigen Skalierungswert angibst, zum Beispiel vmath.vector3(1.0, 2.0, 1.0), wird das Sprite korrekt skaliert, die Kollisionsformen jedoch nicht.
Mit dem Adressierungsmechanismus von Defold kannst du auf jedes Objekt und jede Komponente in einem laufenden Spiel zugreifen. Das Handbuch zur Adressierung erklärt ausführlich, wie das System funktioniert. Du kannst denselben Adressierungsmechanismus auch für dynamisch erzeugte Spielobjekte und deren Komponenten verwenden. Oft genügt die ID des erzeugten Objekts, zum Beispiel beim Senden einer Nachricht:
local function create_hunter(target_id)
local id = factory.create("#hunterfactory")
msg.post(id, "hunt", { target = target_id })
return id
end
Wenn du eine Nachricht an das Spielobjekt selbst statt an eine bestimmte Komponente sendest, wird sie tatsächlich an alle Komponenten gesendet. Das ist normalerweise kein Problem, aber du solltest es im Hinterkopf behalten, wenn das Objekt viele Komponenten hat.
Was aber, wenn du auf eine bestimmte Komponente eines erzeugten Spielobjekts zugreifen musst, zum Beispiel um ein Kollisionsobjekt zu deaktivieren oder das Bild eines Sprites zu ändern? Die Lösung besteht darin, eine URL aus der ID des Spielobjekts und der ID der Komponente zusammenzusetzen.
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
Wenn du factory.create() aufrufst, erhältst du die ID des neuen Spielobjekts zurück und kannst sie für spätere Zugriffe speichern. Häufig erzeugst du Objekte und fügst ihre IDs einer Tabelle hinzu, damit du sie später alle löschen kannst, zum Beispiel beim Zurücksetzen einer Level-Anordnung:
-- 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)
Und später:
-- 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)
Häufig soll das erzeugte Objekt auch das Spielobjekt kennen, das es erzeugt hat. Ein Beispiel wäre ein autonomes Objekt, von dem jeweils nur eines erzeugt werden kann. Das erzeugte Objekt muss dann seinen Erzeuger benachrichtigen, wenn es gelöscht oder deaktiviert wird, damit ein weiteres erzeugt werden kann:
-- 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
Und die Logik des erzeugten Objekts:
-- drone.script
go.property("parent", msg.url())
...
function final(self)
-- I'm dead.
msg.post(self.parent, "drone_dead")
end
Wenn du das Kontrollkästchen Load Dynamically in den Eigenschaften der Fabrik aktivierst, verschiebt die Engine das Laden der mit der Fabrik verknüpften Ressourcen auf einen späteren Zeitpunkt.

Wenn das Kontrollkästchen deaktiviert ist, lädt die Engine die Prototypressourcen beim Laden der Fabrikkomponente, sodass sie sofort zum Erzeugen von Objekten bereitstehen.
Wenn das Kontrollkästchen aktiviert ist, hast du zwei Möglichkeiten:
factory.create() auf, wenn du Objekte erzeugen möchtest. Dadurch werden die Ressourcen synchron geladen, was zu einem kurzen Ruckler führen kann. Anschließend werden neue Instanzen erzeugt.
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() auf, um die Ressourcen ausdrücklich asynchron zu laden. Sobald die Ressourcen zum Erzeugen von Objekten bereitstehen, wird ein Callback aufgerufen.
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
Du kannst ändern, welchen Prototype eine Fabrik erzeugen kann, indem du das Kontrollkästchen Dynamic Prototype in den Eigenschaften der Fabrik aktivierst.

Wenn die Option Dynamic Prototype aktiviert ist, kann die Fabrikkomponente den Prototyp mit der Funktion factory.set_prototype() ändern. Beispiel:
factory.unload("#factory") -- unload the previous resources
factory.set_prototype("#factory", "/main/levels/enemyA.goc")
local enemy_id = factory.create("#factory")
Wenn die Option Dynamic Prototype aktiviert ist, kann die Anzahl der Komponenten in der Sammlung (collection) nicht optimiert werden. Die Sammlung, zu der die Fabrik gehört, verwendet dann die Standardanzahlen für Komponenten aus der Datei game.project.
Die Projekteinstellung Max Instances unter Collection ist die Obergrenze für die Anzahl der Spielobjekte in jeder Sammlung (Welt). Beim Build kann Defold eine kleinere Kapazität zuweisen, wenn sich feststellen lässt, dass dies sicher ist. Alle gleichzeitig existierenden Spielobjekte in einer Welt zählen zu dieser Kapazität, unabhängig davon, ob sie im Editor platziert oder zur Laufzeit erzeugt wurden.

Die tatsächliche Zuweisung hängt von der Analyse beim Build ab:
Richte Max Instances nach der größten Anzahl von Spielobjekten aus, die in einer dynamischen Welt gleichzeitig existieren können. Unter Optimierung der maximalen Komponentenanzahl erfährst du, wie die übrigen Komponentengrenzen berechnet werden.
Es mag sinnvoll erscheinen, erzeugte Spielobjekte in einem Pool zu speichern und wiederzuverwenden. Die Engine verwendet jedoch intern bereits Objektpooling, sodass zusätzlicher Verwaltungsaufwand die Abläufe nur verlangsamt. Spielobjekte zu löschen und neue zu erzeugen ist sowohl schneller als auch sauberer.