Skip to content

Latest commit

Β 

History

History
830 lines (773 loc) Β· 22.9 KB

File metadata and controls

830 lines (773 loc) Β· 22.9 KB

3D .scn Node Fields

Page Map

Header Link
Purpose Purpose
Use Cases Use Cases
Practical Example Practical Example
Reference Reference

Purpose

Copy-and-paste field reference for every 3D node you place in a .scn scene: mesh instances, cameras, lights, physics bodies, skeletons, particles, water, and 3D audio geometry. Each template shows the exact block layout and field names so you can drop a node in and tune values without guessing. For node trees a script builds at runtime, use Node Collections.

Use Cases

  • Place 3D geometry and world text: MeshInstance3D, MultiMeshInstance3D, Sprite3D, Label3D, Decal3D.
  • Add a camera, lights, and sky: Camera3D, PointLight3D, SpotLight3D, RayLight3D, AmbientLight3D, Sky3D.
  • Give things collision and physics: StaticBody3D, RigidBody3D, CharacterBody3D, and Area3D with a child CollisionShape3D.
  • Rig, animate, and attach to skeletons: Skeleton3D, CharacterSkeleton, BoneAttachment3D, AnimationPlayer, AnimationTree, IKTarget3D, PhysicsBoneChain3D.
  • Add particles, water, and audio geometry: ParticleEmitter3D, WaterBody3D, AudioMask3D, AudioEffectZone3D, AudioPortal3D.

Decision Guide

Choose a template by engine behavior first: transform, render, light, camera, or physics. Compose child nodes when one object needs several behaviors. Use typed asset fields for per-instance mesh/material/animation choices and inject their paths through script_vars; keep literal paths in code only for assets shared by every instance.

Practical Example

A minimal 3D scene: a mesh prop plus an active camera looking at it.

[prop]
parent = $root
    [MeshInstance3D]
        mesh = "res://models/barrel.glb:mesh[0]"
        [Node3D]
            position = (0, 0, 0)
        [/Node3D]
    [/MeshInstance3D]
[/prop]

[camera]
parent = $root
    [Camera3D]
        active = true
        [Node3D]
            position = (0, 2, 6)
        [/Node3D]
    [/Camera3D]
[/camera]

Reference

3D .scn Node Fields

Back to index

3D Templates

[node3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [Node3D]
        position = (0, 0, 0)
        rotation = (0, 0, 0, 1)
        scale = (1, 1, 1)
        visible = true
    [/Node3D]
[/node3d]

[mesh_instance_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [MeshInstance3D]
        mesh = "res://path/to/model.glb:mesh[0]"
        material = "res://path/to/material.pmat"
        surfaces = [
            "res://path/to/material0.pmat",
            {
                material = "res://path/to/material1.pmat"
                modulate = (1, 0.9, 0.9, 1)
                overrides = [
                    { name = "roughness", value = 0.25 },
                    { name = "shade_flat", value = true },
                    { name = "rim_color", value = (0.2, 0.6, 1.0, 1.0) }
                ]
            }
        ]
        model = "res://path/to/model.glb"
        skeleton = @SkeletonNodeName
        # indexed glTF blend shape / morph target weights, clamped 0.0..1.0
        # aliases: shape_key_weights, morph_weights
        blend_shape_weights = [0.0, 0.2, 0.1]
        flip_x = false
        flip_y = false
        flip_z = false
        meshlets = true
        blend = {
            enabled = true
            blend_layers = [1]
            blend_mask = [1]
            distance = 0.85
            min_distance = 0.03
            noise = 0.35
            noise_scale = 14.0
            slope_factor = 2.0
            strength = 1.0
            salt_instances = true
        }
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/MeshInstance3D]
[/mesh_instance_3d]

[multi_mesh_instance_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [MultiMeshInstance3D]
        mesh = "res://path/to/model.glb:mesh[0]"
        material = "res://path/to/material.pmat"
        surfaces = [
            "res://path/to/material0.pmat",
            {
                material = "res://path/to/material1.pmat"
                modulate = (1, 0.9, 0.9, 1)
                overrides = [
                    { name = "roughness", value = 0.25 },
                    { name = "shade_flat", value = true }
                ]
            }
        ]
        # instance count = instances.len()
        instance_scale = 1.0
        # default blend shape weights for all instances
        blend_shape_weights = [0.0, 0.2, 0.1]
        flip_x = false
        flip_y = false
        flip_z = false
        meshlets = true
        # alternative to large explicit arrays:
        # instance_grid = { counts=(20, 5, 10) spacing=(1.25, 1.0, 1.25) origin=(-12, 0, -6) scale=(1, 1, 1) scale_wave=0.1 height_wave=0.25 rotation_step_deg=(0, 15, 0) }
        blend_enabled = true
        blend_layers = [1]
        blend_mask = [1]
        blend_distance = 0.85
        instances = [
            {
                position = (6, 0, 0)
                rotation = (0, 0, 0, 1)
                scale = (1, 1, 1)
            },
            {
                position = (6, 0, 0)
                rotation_deg = (0, 45, 0)
                scale = 0.75
                blend_shape_weights = [1.0, 0.0, 0.5]
            },
        ]
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/MultiMeshInstance3D]
[/multi_mesh_instance_3d]

Mesh blending uses screen-space depth to fade mesh intersections.
Only the mesh with `blend_enabled = true` fades.
Receiver meshes only need explicit `blend_layers`.
`blend_enabled = true` applies alpha fade and normal-assisted contact smoothing.
`blend_layers` tags a mesh for blend filtering.
`blend_mask` lists receiver layers the fading mesh ignores.
Default `blend_mask = []`, so enabled blending ignores nothing.
`slope_factor` (0..8, default 2.0) fades the seam on near-perpendicular contacts; 0 turns the slope falloff off.
`strength` (0..1, default 1.0) scales the overall seam blend amount.
`salt_instances` (default true) seams same-type multimesh instances against each other; false shares one seam id per batch (use with many multimesh sources).
Flat aliases: `blend_slope_factor`, `blend_strength`, `blend_salt_instances` (plus `blend_noise_factor`, `blend_noise_scale`).

[sprite3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [Sprite3D]
        texture = "res://path/to/icon.png"
        texture_region = (0, 0, 32, 32)
        size = (1, 1)
        flip_x = false
        flip_y = false
        modulate = (1, 1, 1, 1)
        [Node3D]
            position = (0, 1, -3)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/Sprite3D]
[/sprite3d]

[label3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [Label3D]
        text = "Name"
        # alt: text = %loc: "ui.nameplate"
        # wrap width uses size aspect + font_size, not current camera projection
        size = (1.5, 0.35)
        color = (1, 1, 1, 1)
        lock_orientation = false
        backface_cull = true
        # false: scene-depth test; true: draw as always-visible overlay
        visible_through_objects = false
        # sign style: set opaque backdrop + padding; defaults are transparent + zero
        backdrop_color = (0, 0, 0, 0)
        padding = (0, 0, 0, 0)
        # UI ratio order: top-left, top-right, bottom-right, bottom-left
        corner_radii = (0, 0, 0, 0)
        font_size = 20
        h_align = center
        v_align = center
        [Node3D]
            position = (0, 1.8, -3)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/Label3D]
[/label3d]

[water_body_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [WaterBody3D]
        shape = { type="cube", size=(128, 12, 128) }
        resolution = (128, 128)
        render_resolution = (256, 256)
        lod_min_resolution = (32, 32)
        depth = 12.0
        flow = (0, 0)
        wind = (1, 0)
        idle_mode = "calm"
        wave_speed = 1.0
        wave_scale = 1.0
        damping = 0.985
        buoyancy = 1.0
        drag = 0.35
        wake_strength = 1.35
        foam_strength = 0.9
        sample_readback_rate = 30
        lod_near = 128
        lod_mid = 384
        lod_far = 896
        min_resolution = 32
        collision_layers = [1]
        collision_mask = []
        coastline = { foam_color=(0.9, 0.97, 1.0, 1.0) foam_strength=0.75 foam_width=1.5 cutoff_softness=0.25 wave_reflection=0.45 wave_damping=0.35 edge_noise=0.2 }
        debug = false
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/WaterBody3D]
[/water_body_3d]

[camera3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [Camera3D]
        zoom = 0.0
        projection = perspective
        perspective_fov_y_degrees = 60.0
        perspective_near = 0.1
        perspective_far = 1000.0
        orthographic_size = 10.0
        orthographic_near = 0.1
        orthographic_far = 1000.0
        frustum_left = -1.0
        frustum_right = 1.0
        frustum_bottom = -1.0
        frustum_top = 1.0
        frustum_near = 0.1
        frustum_far = 1000.0
        post_processing = []
        audio_options = { audio_mask=[], effects=[] }
        active = false
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/Camera3D]
[/camera3d]

[camera_stream_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [CameraStream3D]
        camera = @CameraNode
        resolution = (512, 512)
        aspect_ratio = 0.0
        aspect_mode = "fit"
        enabled = true
        size = (1.0, 1.0)
        tint = (1, 1, 1, 1)
        post_processing = []
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/CameraStream3D]
[/camera_stream_3d]

[sub_view_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [SubView3D]
        size = (1, 1)
        resolution = (512, 512)
        aspect_ratio = 0.0
        aspect_mode = "fit"
        view_position = (0, 0, 5)
        view_rotation = (0, 0, 0, 1)
        projection = "perspective"
        perspective_fov_y_degrees = 60
        view_2d_position = (0, 0)
        view_2d_rotation = 0.0
        view_2d_zoom = 1.0
        background = "#00000000"
        tint = (1, 1, 1, 1)
        enabled = true
        suspend_when_hidden = true
        post_processing = []
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/SubView3D]
[/sub_view_3d]

[collision_shape_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [CollisionShape3D]
        shape = { type = cube, size = (1, 1, 1) }
        # alt: trimesh = "res://path/to/model.glb:mesh[0]"
        # alt: shape = { type = trimesh source = "res://path/to/model.glb:mesh[0]" }
        flip_x = false
        flip_y = false
        flip_z = false
        debug = false
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/CollisionShape3D]
[/collision_shape_3d]

[static_body_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [StaticBody3D]
        enabled = true
        friction = 0.7
        restitution = 0.0
        density = 1.0
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/StaticBody3D]
[/static_body_3d]

[rigid_body_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [RigidBody3D]
        enabled = true
        continuous_collision_detection = true
        mass = 1.0
        linear_velocity = (0, 0, 0)
        angular_velocity = (0, 0, 0)
        gravity_scale = 1.0
        linear_damping = 0.0
        angular_damping = 0.0
        can_sleep = true
        friction = 0.7
        restitution = 0.0
        density = 1.0
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/RigidBody3D]
[/rigid_body_3d]

[character_body_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [CharacterBody3D]
        enabled = true
        friction = 0.7
        restitution = 0.0
        density = 1.0
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/CharacterBody3D]
[/character_body_3d]

[area3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [Area3D]
        enabled = true
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/Area3D]
[/area3d]

[audio_mask_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [AudioMask3D]
        active = true
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/AudioMask3D]
[/audio_mask_3d]

[audio_effect_zone_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [AudioEffectZone3D]
        active = true
        audio_mask = []
        effects = [
            { reverb_send = 0.35 echo = 0.0 dampening = 0.0 }
        ]
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/AudioEffectZone3D]
[/audio_effect_zone_3d]

[audio_portal_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [AudioPortal3D]
        active = true
        strength = 1.0
        targets = [@OtherPortal]
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/AudioPortal3D]
[/audio_portal_3d]

[skeleton3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [Skeleton3D]
        skeleton = "res://path/to/model.glb:skeleton[0]"
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/Skeleton3D]
[/skeleton3d]

[bone_attachment_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [BoneAttachment3D]
        skeleton = @SkeletonNodeName
        bone = 0
        # alt: bone_index = 0
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/BoneAttachment3D]
[/bone_attachment_3d]

[physics_bone_chain_3d]
    [PhysicsBoneChain3D]
        skeleton = @SkeletonNodeName
        bone = 0
        chain_length = 4
        gravity = (0, -9.81, 0)
        damping = 0.08
        stiffness = 0.35
        radius = 0.05
        collisions = true
        iterations = 3
    [/PhysicsBoneChain3D]
[/physics_bone_chain_3d]

[bone_collider_3d]
    [BoneCollider3D]
        enabled = true
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/BoneCollider3D]
[/bone_collider_3d]

[ik_target_3d]
parent = PARENTKEY
script = "res://path/to/script.rs"
    [IKTarget3D]
        skeleton = @SkeletonNodeName
        bone = 0
        # alt: bone_index = 0
        chain_length = 2
        iterations = 8
        tolerance = 0.01
        weight = 1.0
        match_rotation = true
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/IKTarget3D]
[/ik_target_3d]

[particle_emitter_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [ParticleEmitter3D]
        active = true
        looping = true
        prewarm = false
        spawn_rate = 256.0
        seed = 1
        params = []
        profile = "res://path/to/profile.ppart"
        sim_mode = default
        render_mode = point
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/ParticleEmitter3D]
[/particle_emitter_3d]

[particle_emitter_2d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [ParticleEmitter2D]
        active = true
        looping = true
        prewarm = false
        spawn_rate = 256.0
        seed = 1
        params = []
        profile = "res://path/to/profile.ppart"
        sim_mode = default
        [Node2D]
            position = (0, 0)
            rotation = 0
            scale = (1, 1)
            z_index = 0
            visible = true
        [/Node2D]
    [/ParticleEmitter2D]
[/particle_emitter_2d]

Bone Attachment Example

BoneAttachment3D binds to a Skeleton3D node plus bone index. Children then inherit that bone transform. Use it for socket nodes, like a sword in a hand.

[CharacterSkeleton]
parent = @Character
    [Skeleton3D]
        skeleton = "res://characters/hero.glb:skeleton[0]"
    [/Skeleton3D]
[/CharacterSkeleton]

[RightHandSocket]
parent = @Character
    [BoneAttachment3D]
        skeleton = @CharacterSkeleton
        bone = 15
    [/BoneAttachment3D]
[/RightHandSocket]

[Sword]
parent = @RightHandSocket
    [MeshInstance3D]
        mesh = "res://weapons/sword.glb:mesh[0]"
        material = "res://weapons/sword.pmat"
        [Node3D]
            position = (0.05, 0.0, 0.0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/MeshInstance3D]
[/Sword]

Lights And Resource Templates

[ambient_light_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [AmbientLight3D]
        color = (1, 1, 1)
        intensity = 0.0
        cast_shadows = true
        active = true
    [/AmbientLight3D]
[/ambient_light_3d]

[sky3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [Sky3D]
        day_colors = [
            (0.55, 0.82, 1.0),
            (0.38, 0.68, 0.95),
            (0.18, 0.45, 0.82)
        ]
        evening_colors = [
            (1.00, 0.62, 0.40),
            (0.95, 0.42, 0.58),
            (0.42, 0.20, 0.42)
        ]
        night_colors = [
            (0.01, 0.02, 0.06),
            (0.04, 0.06, 0.15),
            (0.09, 0.12, 0.25)
        ]
        horizon_colors = [
            (0.62, 0.64, 0.66),
            (0.42, 0.43, 0.45),
            (0.28, 0.29, 0.31)
        ]
        time = { time_of_day = 0.25 paused = false scale = 1.0 }
        time_of_day = 0.25
        time_paused = false
        time_scale = 1.0
        shaders = [
            { path = "res://path/to/sky.wgsl", params = [0.5, (1.0, 0.8, 0.6)] }
        ]
        environment = {
            source = "res://textures/studio.png"
            intensity = 1.0
            rotation_degrees = 0.0
        }
        active = true
    [/Sky3D]
[/sky3d]

See [`Sky3D`](../../resources/sky3d.md) for custom sky shader authoring.

[ray_light_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [RayLight3D]
        color = (1, 1, 1)
        intensity = 1.0
        cast_shadows = true
        shadow = { strength = 0.82 depth_bias = 0.00003 normal_bias = 0.005 }
        active = true
        visible = true
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/RayLight3D]
[/ray_light_3d]

[point_light_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [PointLight3D]
        color = (1, 1, 1)
        intensity = 1.0
        range = 10.0
        cast_shadows = true
        shadow_strength = 0.82
        shadow_depth_bias = 0.00003
        shadow_normal_bias = 0.005
        active = true
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/PointLight3D]
[/point_light_3d]

[spot_light_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [SpotLight3D]
        color = (1, 1, 1)
        intensity = 1.0
        range = 12.0
        inner_angle_radians = 0.34906584
        outer_angle_radians = 0.5235988
        cast_shadows = true
        shadow_strength = 0.82
        shadow_depth_bias = 0.00003
        shadow_normal_bias = 0.005
        active = true
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/SpotLight3D]
[/spot_light_3d]

[decal_3d]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [Decal3D]
        size = (1, 1, 1)
        albedo_texture = "res://textures/decal.png"
        normal_texture = ""
        emission_texture = ""
        modulate = (1, 1, 1, 1)
        albedo_mix = 1.0
        emission_energy = 1.0
        normal_strength = 1.0
        normal_fade = 0.3
        distance_fade_begin = 0.0
        distance_fade_length = 8.0
        sort_priority = 0
        active = true
        [Node3D]
            position = (0, 0, 0)
            rotation = (0, 0, 0, 1)
            scale = (1, 1, 1)
            visible = true
        [/Node3D]
    [/Decal3D]
[/decal_3d]

Decal3D projects along its local -Z axis onto lit geometry inside the `size`
box, patching albedo/normal and adding emission before lighting (decals
receive shadows and lights like the surface under them). `normal_fade`
rejects grazing surfaces, `distance_fade_begin`/`distance_fade_length` fade
by camera distance (0 = never), higher `sort_priority` blends over lower.

[animation_player]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [AnimationPlayer]
        animation = "res://path/to/clip.panim"
        bindings = []
        speed = 1.0
        paused = false
        playback = loop
    [/AnimationPlayer]
[/animation_player]

[animation_tree]
parent = @PARENTKEY
script = "res://path/to/script.rs"
    [AnimationTree]
        tree = "res://path/to/tree.panimtree"
        animations = [
            { animation = "res://path/to/idle.panim", bindings = { Hero = @PlayerRoot }, playback = loop, speed = 1.0, paused = false },
            { animation = "res://path/to/run.panim", bindings = { Hero = @PlayerRoot }, playback = loop, speed = 1.0, paused = false },
            { animation = "res://path/to/aim.panim", bindings = { Hero = @PlayerRoot }, playback = boomerang, speed = 1.0, paused = false },
        ]
        speed = 1.0
        paused = false
    [/AnimationTree]
[/animation_tree]