Zurück zum Blog

Defold wird vollständig 3D: Ein Technical Breakdown und Architektur-Tutorial

Veröffentlicht am 12. Mai 2026
Defold wird vollständig 3D: Ein Technical Breakdown und Architektur-Tutorial

Kurz und knapp

Defold hat sich erfolgreich zur vollwertigen 3D Game Engine entwickelt und bietet Indie-Entwicklern eine performante, leichtgewichtige Alternative für Web- und Mobile-Projekte. Dieser technische Breakdown erläutert die Implementierung von Custom Render-Scripts, First-Person-Kameras und die Optimierung von Rendering Pipelines sowie Networking-Daten. Durch die Nutzung von Backend-Services wie horizOn lassen sich komplexe Infrastruktur-Hürden bei Multiplayer-Anwendungen effizient überwinden.

Jeder Indie-Entwickler kennt den Moment, in dem die Game Engine einen im Stich lässt. Man beginnt mit einem leichtgewichtigen 2D-Konzept, durch Scope Creep kommen 3D-Elemente hinzu, und plötzlich explodiert die Build-Größe der Engine, die Ladezeiten kriechen dahin und die Web-Builds stürzen wegen Out-of-Memory-Fehlern ab. Massive Engines wie Unity und Unreal sind phänomenal für AAA-Fidelity, aber für Solo-Entwickler, die auf eine reibungslose Cross-Platform-Distribution abzielen – besonders WebGL und Mobile – fühlen sie sich oft so an, als würde man mit einem Panzer zum Supermarkt fahren.

Vorhang auf für Defold. Historisch als ultra-schnelle, Zero-Bloat 2D-Engine geschätzt, die von Studios genutzt wird, um jede Plattform von HTML5 bis Nintendo Switch mit einer einzigen Codebase zu bedienen, ist Defold nun offiziell erwachsen geworden. Es ist jetzt eine voll einsatzfähige 3D Game Engine. Während es technisch gesehen unter der Haube schon immer in einem 3D-Kontext gerendert hat (indem flache Ebenen über eine orthografische Kamera projiziert wurden), haben die jüngsten Updates dedizierte 3D-Tooling-Funktionen, vollständigen glTF Mesh-Support und einen optimierten Workflow für echte 3D-Entwicklung eingeführt.

Dies ist ein massiver Shift für das Ecosystem. Wenn Sie nach einer Engine suchen, die in Sekunden kompiliert, einstellige Megabyte-Binaries erzeugt und Ihnen dennoch die Power gibt, dynamische 3D-Welten zu rendern, ist Defold nun ein Top-Tier-Anwärter. In diesem Defold 3D Game Engine Tutorial und Architektur-Breakdown werden wir tief in die Funktionsweise der Defold Rendering Pipeline eintauchen, ein Custom 3D-Kamera-Script von Grund auf schreiben und die Backend-Implikationen für das Networking eines leichtgewichtigen 3D-Spiels untersuchen.

Under the Hood: Die Realität der Defold 3D Pipeline

Um zu verstehen, wie man Defold in 3D beherrscht, muss man dessen Rendering-Philosophie begreifen. Defold liefert Ihnen keinen vorkonfigurierten PBR (Physically Based Rendering) Pipeline out of the box, wie es die Unreal Engine tut. Stattdessen bietet es ein hochoptimiertes, datengesteuertes Render-Script, das in Lua geschrieben ist.

Alles, was in Defold auf dem Bildschirm gezeichnet wird, wird von einem render_script verwaltet. Standardmäßig ist dieses Script für 2D konfiguriert. Es richtet eine orthografische Projection Matrix ein, sortiert Sprites nach ihrem Z-Value (Tiefe) und zeichnet sie von hinten nach vorne. Um die 3D-Fähigkeiten von Defold freizuschalten, müssen wir dieses Script umschreiben, um eine perspektivische Projection Matrix zu verwenden, Hardware Depth Testing zu aktivieren und Custom Render Predicates für unsere 3D-Modelle zu definieren.

Dieser Low-Level-Zugriff ist ein zweischneidiges Schwert. Einerseits müssen Sie ein wenig Matrix-Mathematik schreiben. Andererseits haben Sie die absolute Kontrolle über Ihre Draw Calls, was es Ihnen ermöglicht, das Rendering für Ultra-Low-End-Hardware auf eine Weise zu optimieren, die monolithische Engines unglaublich schwierig machen.

Architektur Ihres Custom 3D Render-Scripts

Um echte 3D-Modelle zu rendern, ohne dass sie sich basierend auf der Zeichenreihenfolge falsch überlagern, müssen wir den Depth Buffer (Z-buffer) aktivieren. Hier ist ein grundlegendes 3D Render-Script, das die Standard-Pipeline von Defold ersetzt.

-- main/3d_pipeline.render_script
function init(self)
    -- Define the background clear color (RGBA)
    self.clear_color = vmath.vector4(0.1, 0.1, 0.12, 1.0)
    self.clear_buffers = {
        [render.BUFFER_COLOR_BIT] = self.clear_color,
        [render.BUFFER_DEPTH_BIT] = 1.0,
        [render.BUFFER_STENCIL_BIT] = 0
    }

    -- Create render predicates. 'model' is the default tag for 3D meshes
    self.predicates = {
        model = render.predicate({"model"}),
        gui = render.predicate({"gui"}),
        text = render.predicate({"text"})
    }
end

function update(self)
    -- 1. Setup the rendering state for the frame
    render.set_depth_mask(true)
    render.set_stencil_mask(0xff)
    render.clear(self.clear_buffers)

    -- 2. Configure the 3D Camera Projection
    local window_width = render.get_window_width()
    local window_height = render.get_window_height()
    if window_width == 0 or window_height == 0 then return end
    
    local aspect_ratio = window_width / window_height
    local fov = math.rad(60) -- 60 degree Field of View
    local near_z = 0.1
    local far_z = 1000.0
    
    local proj_matrix = vmath.matrix4_perspective(fov, aspect_ratio, near_z, far_z)
    render.set_projection(proj_matrix)

    -- 3. Draw 3D Models with Depth Testing enabled
    render.set_depth_test(render.COMPARE_LEQUAL)
    render.set_cull_face(render.FACE_BACK)
    render.set_blend_func(render.BLEND_SRC_ALPHA, render.BLEND_ONE_MINUS_SRC_ALPHA)
    
    -- The view matrix is passed via messages from our camera script
    if self.view_matrix then
        render.set_view(self.view_matrix)
        render.draw(self.predicates.model)
    end

    -- 4. Draw GUI over the 3D scene (Orthographic)
    render.set_depth_mask(false)
    render.set_depth_test(render.COMPARE_ALWAYS)
    local gui_proj = vmath.matrix4_orthographic(0, window_width, 0, window_height, -1, 1)
    render.set_projection(gui_proj)
    render.set_view(vmath.matrix4())
    
    render.draw(self.predicates.gui)
    render.draw(self.predicates.text)
end

function on_message(self, message_id, message)
    if message_id == hash("set_view_matrix") then
        self.view_matrix = message.matrix
    end
end

Beachten Sie, wie explizit wir hier den Status verwalten. Wir leeren den Depth Buffer, berechnen die perspektivische Matrix basierend auf den aktuellen Fensterabmessungen, erzwingen Back-Face Culling, um Rasterisierungszyklen zu sparen, und schalten schließlich die Projection Matrix zurück auf orthografisch, bevor wir das GUI rendern. Dies ergibt eine robuste Split-Pipeline Rendering-Architektur.

Bau eines First-Person 3D-Kamera-Controllers

Ein Render-Script allein wird Ihnen ohne eine Kamera, die sich durch den Raum bewegt, nicht viel zeigen. Defold operiert stark auf einer Message Passing Architektur. Im Gegensatz zu objektorientierten Engines, bei denen die Kamera direkt transform.Translate() aufrufen könnte, berechnet unser Kamera-Script in Defold seine View Matrix und sendet sie per Dispatch an das soeben geschriebene Render-Script.

Lassen Sie uns eine Standard First-Person-Kamera konstruieren, die Mouse-Look (Pitch und Yaw) und Tastaturbewegung (WASD) verarbeitet.

-- scripts/camera_controller.script
go.property("mouse_sensitivity", 0.2)
go.property("move_speed", 10.0)

function init(self)
    msg.post(".", "acquire_input_focus")
    self.pitch = 0
    self.yaw = 0
    
    -- Hide and capture the mouse cursor
    window.set_mouse_lock(true)
    
    self.forward = vmath.vector3(0, 0, -1)
    self.right = vmath.vector3(1, 0, 0)
    self.up = vmath.vector3(0, 1, 0)
    self.velocity = vmath.vector3(0)
end

function update(self, dt)
    local pos = go.get_position()
    
    -- Apply movement velocity
    if vmath.length_sqr(self.velocity) > 0 then
        local move_dir = vmath.normalize(self.velocity)
        pos = pos + move_dir * self.move_speed * dt
        go.set_position(pos)
    end

    -- Calculate the view matrix
    local rotation = go.get_rotation()
    self.forward = vmath.rotate(rotation, vmath.vector3(0, 0, -1))
    local target = pos + self.forward
    
    local view_matrix = vmath.matrix4_look_at(pos, target, self.up)
    
    -- Send the calculated view matrix to the render pipeline
    msg.post("@render:", "set_view_matrix", { matrix = view_matrix })
    
    -- Reset velocity for the next frame
    self.velocity = vmath.vector3(0)
end

function on_input(self, action_id, action)
    if action_id == hash("mouse_moved") then
        self.yaw = self.yaw - action.dx * self.mouse_sensitivity
        self.pitch = self.pitch + action.dy * self.mouse_sensitivity
        
        -- Clamp pitch to prevent the camera from flipping over
        self.pitch = math.max(-89, math.min(89, self.pitch))
        
        -- Convert Euler angles to a Quaternion
        local rot_y = vmath.quat_rotation_y(math.rad(self.yaw))
        local rot_x = vmath.quat_rotation_x(math.rad(self.pitch))
        go.set_rotation(rot_y * rot_x)
        
    elseif action_id == hash("move_forward") then
        self.velocity = self.velocity + self.forward
    elseif action_id == hash("move_backward") then
        self.velocity = self.velocity - self.forward
    elseif action_id == hash("move_left") then
        self.right = vmath.cross(self.forward, self.up)
        self.velocity = self.velocity - self.right
    elseif action_id == hash("move_right") then
        self.right = vmath.cross(self.forward, self.up)
        self.velocity = self.velocity + self.right
    end
end

Dieses Script erfasst Maus-Delta-Bewegungen, um Pitch und Yaw anzupassen, und wandelt diese Euler Angles in eine robuste Quaternion-Rotation um. Es leitet dann die Forward- und Right-Vektoren direkt aus dieser Rotation ab, um sicherzustellen, dass das Drücken von "W" Sie immer in die Richtung bewegt, in die Sie gerade schauen.

3D Asset Integration und Custom Shader

Mit den neuesten Updates von Defold ist das Einbinden von 3D-Assets in Ihr Projekt trivial. Die Engine unterstützt nativ die Formate .gltf und .glb, die zum Industriestandard für Web- und leichtgewichtige Spieleentwicklung geworden sind.

Das Rendern eines Mesh erfordert jedoch ein Material, und Materialien erfordern Shader. Standardmäßig enthält Defold Basismaterialien, aber das Schreiben eigener GLSL Shader verleiht Ihnen die visuelle Eigenständigkeit, die notwendig ist, um aufzufallen. Schreiben wir einen schnellen, unlit Textured Shader, der perfekt für Mobile- oder HTML5-Targets optimiert ist.

Der Vertex Shader (model.vp)

// model.vp
uniform highp mat4 view_proj;
uniform highp mat4 world;

attribute highp vec4 position;
attribute mediump vec2 texcoord0;

varying mediump vec2 var_texcoord0;

void main()
{
    // Calculate the final screen-space position of the vertex
    vec4 p = view_proj * world * vec4(position.xyz, 1.0);
    var_texcoord0 = texcoord0;
    gl_Position = p;
}

Der Fragment Shader (model.fp)

// model.fp
varying mediump vec2 var_texcoord0;
uniform lowp sampler2D texture_sampler;
uniform lowp vec4 tint;

void main()
{
    // Sample the texture and multiply by a color tint
    lowp vec4 tex_color = texture2D(texture_sampler, var_texcoord0.xy);
    gl_FragColor = tex_color * tint;
}

In Ihrer Defold-Materialdatei ordnen Sie das view_proj Uniform der integrierten View-Projection Matrix der Engine zu und texture_sampler der Diffuse-Textur Ihres Mesh. Da diese Shader keine dynamische Beleuchtung oder Shadow Maps berechnen, laufen sie unglaublich schnell, was es Ihnen ermöglicht, mühelos 60 FPS auf Low-End-Hardware beizubehalten.

Handhabung von 3D Multiplayer und State Synchronization

Wenn Sie von einem 2D Grid-basierten Spiel zu einer vollen 3D-Umgebung übergehen, steigt die Komplexität Ihrer Networking-Architektur exponentiell an. Der Wechsel von 2D zu 3D bedeutet, dass Ihre State Synchronization nun die Z-Achsen-Tiefe, Floating-Point-Ungenauigkeiten über Physics Engines hinweg und volle Quaternion-Rotationen berücksichtigen muss. Wenn Sie dies schlecht handhaben, werden Sie mit schwerem visual Stuttering enden – ein häufiges Problem, das wir analysiert haben, als wir untersuchten, How To Fix Player Location Desync In Uefn And Unreal Engine Multiplayer.

Da Defold eine Lightweight Engine ist, verfügt sie nicht über ein schwerfälliges, integriertes Replication-System wie die RPCs der Unreal Engine. Sie sind dafür verantwortlich, Ihre Statusdaten effizient zu packen.

Sich auf REST APIs zu verlassen, um 3D-Positionen zu synchronisieren, wird Ihren Game Loop sofort ausbremsen. Stattdessen benötigen Sie persistente, bidirektionale Verbindungen. Während unser vorheriger Guide behandelte, wie man Ditch Http Polling An Unreal Engine Websockets Tutorial For Real Time Backends, gelten genau dieselben Architekturprinzipien direkt für die Lua-basierten WebSocket-Extensions von Defold.

Hier ist ein Beispiel, wie Sie 3D-Transform-Daten serialisieren sollten, um die Payload-Größe über WebSockets zu minimieren:

-- scripts/network_sync.lua
local json = require "builtins.scripts.json"

function serialize_transform(go_id)
    local pos = go.get_position(go_id)
    local rot = go.get_rotation(go_id)
    
    -- Compress the payload to the absolute minimum required data
    -- We round position to 2 decimal places to save bandwidth
    local payload = {
        id = hash_to_hex(go_id),
        x = math.floor(pos.x * 100) / 100,
        y = math.floor(pos.y * 100) / 100,
        z = math.floor(pos.z * 100) / 100,
        -- Quaternions require all 4 components for accurate reconstruction
        qx = rot.x,
        qy = rot.y,
        qz = rot.z,
        qw = rot.w
    }
    
    return json.encode(payload)
end

Durch das Runden der Floats und das Packen nur wesentlicher Daten verhindern Sie, dass Ihre Network Buffer bei schnellen Bewegungs-Updates überlaufen. Das Management dieses Flows ist der Schlüssel zu responsivem Cross-Platform-Play.

Die Infrastruktur-Last von Cross-Platform 3D

Einen hochoptimierten 3D Game Client in Defold zu schreiben, ist immens befriedigend. Die Engine bleibt Ihnen aus dem Weg, kompiliert in Millisekunden und lässt Sie sich strikt auf die Logik konzentrieren.

Doch in dem Moment, in dem Sie sich entscheiden, dieses 3D-Spiel zum Multiplayer zu machen, Cloud-Saves hinzuzufügen oder Cross-Platform Leaderboards zu implementieren, verlagert sich Ihr Fokus sofort von der Spieleentwicklung hin zur Server-Orchestrierung. Sie finden sich plötzlich beim Schreiben von Dockerfiles wieder, konfigurieren Kubernetes-Cluster, kämpfen mit Redis-Instanzen für den Session-State und versuchen, Ihre WebSocket-Gateways gegen DDoS-Attacken zu sichern.

Dies selbst zu bauen, erfordert das Einrichten von Load Balancern, Database Sharding und SSL-Zertifikatsmanagement – locker 4 bis 6 Wochen Arbeit, nur um einen zuverlässigen Prototypen zum Laufen zu bringen.

Mit horizOn sind diese Backend-Services vorkonfiguriert, sodass Sie Ihr Spiel ausliefern können statt Ihrer Infrastruktur. horizOn bietet native Integrationen für User Authentication, Real-Time Database Syncing und Server-authoritative Logik und schließt damit perfekt die Lücke für Lightweight Engines wie Defold, die nicht mit proprietären Backend-Ecosystemen ausgeliefert werden. Sie behalten die Geschwindigkeit einer winzigen Client-Engine bei, während Sie das Heavy Lifting der Server-Architektur auslagern.

Best Practices für die Defold 3D-Entwicklung

Wenn Sie planen, ein kommerziell tragfähiges 3D-Projekt in Defold zu bauen, halten Sie sich strikt an diese Architektur-Richtlinien:

  1. Geometrie stark optimiert halten: Defold ist auf Geschwindigkeit ausgelegt. Um den Lightweight-Vorteil zu wahren, halten Sie Ihre Level-Geometrie unter 100.000 Polygonen insgesamt pro Szene, besonders wenn Sie auf HTML5/WebGL abzielen. Verwenden Sie gebackene Normal Maps anstelle von High-Density Meshes, um Details zu simulieren.
  2. Render Predicates für Frustum Culling nutzen: Defold cullt Objekte, die sich außerhalb der Kameraansicht im 3D-Raum befinden, nicht automatisch out of the box. Sie müssen eine eigene Frustum Culling Logik in Lua schreiben und die Model-Komponenten von Objekten, die außerhalb der Bounds liegen, dynamisch deaktivieren, um Rasterisierungszeit zu sparen.
  3. Draw Calls durch Atlasing konsolidieren: Jedes einzigartige Material und jede Textur erfordert einen separaten Draw Call, der an die GPU gesendet wird. Kombinieren Sie Ihre Texturen in großen Textur-Atlanten. Wenn 10 verschiedene 3D-Modelle exakt dasselbe Material und denselben Atlas teilen, kann Defold sie unter der Haube viel effizienter batchen.
  4. Komplexe Mathematik vorausberechnen: Matrix-Multiplikationen und Quaternion-Konvertierungen sind in Lua hochgradig rechenintensive Operationen. Cachen Sie Ihre Forward- und Right-Vektoren und berechnen Sie diese nur neu, wenn sich die Rotation des Spielers tatsächlich ändert, anstatt die schwere Mathematik bedingungslos in jedem einzelnen Frame durchzuführen.
  5. Logik von der Render-Frequenz entkoppeln: Ihre Spiellogik (update) mag mit 60 FPS laufen, aber Ihre Custom Physics- oder Networking-Schritte ticken vielleicht mit 30 FPS. Interpolieren Sie Ihre visuellen 3D-Positionen basierend auf der Velocity, anstatt sie direkt auf den neuesten Status zu snappen, um ein butterweiches Rendering auf unterschiedlichen Monitor-Bildwiederholraten zu gewährleisten.
  6. Lua Garbage Collection verwalten: In einer dynamischen 3D-Umgebung erstellen und zerstören Sie häufig Vektor-Objekte und Matrizen. Der Garbage Collector von Lua kann spürbare Frame Spikes verursachen, wenn er nicht verwaltet wird. Verwenden Sie vmath.vector3 und vmath.matrix4 Instanzen wieder, wann immer möglich, indem Sie deren interne Werte direkt aktualisieren, anstatt neue lokale Variablen innerhalb Ihres update Loops zu instanziieren. Reservieren Sie Memory Pools für Bullets und Entities vorab.
  7. Beleuchtung extern baken: Da dynamische Beleuchtung in Custom GLSL Shadern Ihr Performance-Budget auf Mobilgeräten schnell auffrisst, baken Sie Ihre Global Illumination und Ambient Occlusion direkt in Ihre Texturen mit Blender oder Maya, bevor Sie Ihre glTF-Modelle exportieren. Ein einfacher Unlit Shader mit wunderschön gebackener Beleuchtung wird einen komplexen dynamischen Shader in mobilen Webbrowsern immer schlagen.

Fazit

Die Entwicklung von Defold zu einer robusten 3D Game Engine ist ein massiver Gewinn für unabhängige Entwickler. Es behält erfolgreich seine blitzschnellen Compile-Zeiten und unglaublich kleinen Binary-Footprints bei, während es die mathematischen Grundlagen und Tools bietet, die zum Bau expansiver, fesselnder 3D-Welten erforderlich sind. Durch das Beherrschen von Custom Render-Scripts, das Verständnis von Matrix-Operationen und das effiziente Serialisieren Ihrer Netzwerkdaten können Sie Cross-Platform-Titel bauen, die technisch mit viel größeren, Bloat-lastigen Engines konkurrieren.

Wenn Sie bereit sind, Ihren hochoptimierten 3D-Client online zu bringen und Ihr Multiplayer-Backend zu skalieren, ohne den Kopfschmerz der Verwaltung roher Infrastruktur, testen Sie horizOn kostenlos oder werfen Sie einen Blick in die API docs, um zu sehen, wie schnell Sie Real-Time-Services in Ihr nächstes Defold-Projekt integrieren können.


Quelle: Defold is Now a Full 3D Game Engine