WIP: Project Documentation Generator (for help posts in this forum)

The Project Documentation Generator is a Godot plugin designed to help developers quickly and easily share comprehensive details about their projects on the Godot forums. This tool automatically collects and formats key information about your project, including:

Scene structures
Script contents
Signal connections
Changed node properties
Resource details
Shader code
Project settings

With customizable options and the ability to exclude specific directories, this plugin streamlines the process of creating detailed project overviews. It’s perfect for when you need to share your project structure for troubleshooting, code reviews, or collaboration. Simply generate the documentation, copy the formatted output, and paste it into your forum post to provide a clear, organized view of your project to those offering assistance.

You can find it here:

So, what does it look like when it is used? I will add a post below running it on Kenney’s 3D platform starter kit to show as an example.

3 Likes

Obviously, this would be pretty huge to post the whole thing, so here a a pretty big selection of things. I wanted to see what a forum post of someone else’s project would look like.

You can also exclude directories and exclude sections (like only export scene trees and project settings).

4.3-stable (official) 77dcf97d8

Project Settings
config_version: <null>
application
config/name: Starter Kit 3D Platformer
config/tags: ["starterkit"]
run/main_scene: res://scenes/main.tscn
config/features: ["4.3", "Forward Plus"]
boot_splash/bg_color: (0.9255, 0.9255, 0.9608, 1)
boot_splash/image: res://splash-screen.png
config/icon: res://icon.png
autoload
Audio: res://scripts/audio.gd (disabled)
display
window/size/viewport_width: 1280
window/size/viewport_height: 720
editor
movie_writer/movie_file: C:/Users/Kenney/Desktop/video-footage.avi
editor_plugins
enabled: ["res://addons/project_documentation/plugin.cfg"]
filesystem
import/blender/enabled: false
input
move_right: { "deadzone": 0.25, "events": [InputEventKey: keycode=68 (D), mods=none, physical=true, location=unspecified, pressed=false, echo=false, InputEventJoypadMotion: axis=0, axis_value=1.00] }
move_left: { "deadzone": 0.25, "events": [InputEventKey: keycode=65 (A), mods=none, physical=true, location=unspecified, pressed=false, echo=false, InputEventJoypadMotion: axis=0, axis_value=-1.00] }
move_forward: { "deadzone": 0.25, "events": [InputEventKey: keycode=87 (W), mods=none, physical=true, location=unspecified, pressed=false, echo=false, InputEventJoypadMotion: axis=1, axis_value=-1.00] }
move_back: { "deadzone": 0.25, "events": [InputEventKey: keycode=83 (S), mods=none, physical=true, location=unspecified, pressed=false, echo=false, InputEventJoypadMotion: axis=1, axis_value=1.00] }
jump: { "deadzone": 0.5, "events": [InputEventKey: keycode=32 (Space), mods=none, physical=true, location=unspecified, pressed=false, echo=false, InputEventJoypadButton: button_index=1, pressed=true, pressure=0.00] }
camera_left: { "deadzone": 0.5, "events": [InputEventKey: keycode=4194319 (Left), mods=none, physical=true, location=unspecified, pressed=false, echo=false, InputEventJoypadMotion: axis=2, axis_value=-1.00] }
camera_right: { "deadzone": 0.5, "events": [InputEventKey: keycode=4194321 (Right), mods=none, physical=true, location=unspecified, pressed=false, echo=false, InputEventJoypadMotion: axis=2, axis_value=1.00] }
camera_up: { "deadzone": 0.5, "events": [InputEventKey: keycode=4194320 (Up), mods=none, physical=true, location=unspecified, pressed=false, echo=false, InputEventJoypadMotion: axis=3, axis_value=-1.00] }
camera_down: { "deadzone": 0.5, "events": [InputEventKey: keycode=4194322 (Down), mods=none, physical=true, location=unspecified, pressed=false, echo=false, InputEventJoypadMotion: axis=3, axis_value=1.00] }
zoom_in: { "deadzone": 0.5, "events": [InputEventKey: keycode=4194437 (Kp Add), mods=none, physical=true, location=unspecified, pressed=false, echo=false, InputEventJoypadMotion: axis=5, axis_value=1.00] }
zoom_out: { "deadzone": 0.5, "events": [InputEventKey: keycode=4194435 (Kp Subtract), mods=none, physical=true, location=unspecified, pressed=false, echo=false, InputEventJoypadMotion: axis=4, axis_value=1.00] }
rendering
anti_aliasing/quality/screen_space_aa: 1

Scenes

res://objects/character.tscn
Scene Tree
character ( res://models/character.glb)
      leg-left ()
      leg-right ()
      torso ()
        arm-left ()
        arm-right ()
        antenna ()
  AnimationPlayer ()
Signal Connections
  Signal Connections:
    None
Nodes
. ( res://models/character.glb)

Changed Properties:
None

./character/root/leg-left ()

Changed Properties:

  transform = [X: (0.965926, 0, -0.258819), Y: (0, 1, 0), Z: (0.258819, 0, 0.965926), O: (0.125, 0.17625, -0.02375)]
./character/root/leg-right ()

Changed Properties:

  transform = [X: (0.965926, 0, 0.258819), Y: (0, 1, 0), Z: (-0.258819, 0, 0.965926), O: (-0.125, 0.17625, -0.02375)]
./character/root/torso ()

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 0.996194, -0.087156), Z: (0, 0.087156, 0.996194), O: (-0, 0.17625, -0.02375)]
./character/root/torso/arm-left ()

Changed Properties:

  transform = [X: (0.707107, -0.707107, 0), Y: (0.707107, 0.707107, 0), Z: (0, 0, 1), O: (0.3, 0.175, 0)]
./character/root/torso/arm-right ()

Changed Properties:

  transform = [X: (0.707107, 0.707107, 0), Y: (-0.707107, 0.707107, 0), Z: (0, 0, 1), O: (-0.3, 0.1195, 0)]
./character/root/torso/antenna ()

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 0.999999, 0), Z: (0, 0, 0.999999), O: (0, 0.6, 0)]
./AnimationPlayer ()

Changed Properties:

  deterministic = true
  playback_default_blend_time = 0.2
res://objects/cloud.tscn
Scene Tree
cube ( res://models/cloud.glb)
Signal Connections
  Signal Connections:
    None
Nodes
. ( res://models/cloud.glb)

Script: res://objects/cloud.gd
Changed Properties:
None

res://objects/coin.tscn
Scene Tree
coin (Area3D)
  Mesh (MeshInstance3D)
  CollisionShape3D (CollisionShape3D)
  Particles (CPUParticles3D)
Signal Connections
  Signal Connections:
    ..body_entered -> .._on_body_entered (Flags: PERSIST)
Nodes
. (Area3D)

Script: res://objects/coin.gd
Changed Properties:
None

./Mesh (MeshInstance3D)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (0, 0.25, 0)]
  mesh = res://objects/coin.tscn::ArrayMesh_t08aw
  skeleton = 
  surface_material_override/0 = res://objects/coin.tscn::StandardMaterial3D_xkafy
./CollisionShape3D (CollisionShape3D)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (0, 0.5, 0)]
  shape = res://objects/coin.tscn::SphereShape3D_bnkeq
./Particles (CPUParticles3D)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (0, 0.447834, 0)]
  material_override = res://objects/coin.tscn::StandardMaterial3D_6hm51
  mesh = res://objects/coin.tscn::QuadMesh_744xy
  direction = (1, 1, 1)
  spread = 180
  gravity = (0, 0, 0)
  initial_velocity_max = 1
  damping_min = 0.5
  damping_max = 0.5
  scale_amount_min = 0.15
  scale_amount_max = 0.15
  scale_amount_curve = res://objects/coin.tscn::Curve_6a7l3
  color_ramp = res://objects/coin.tscn::Gradient_7tsk2
res://objects/platform.tscn
Scene Tree
platform ( res://models/platform.glb)
  platform2#StaticBody3D (StaticBody3D)
    platform2_StaticBody3D#CollisionShape3D (CollisionShape3D)
Signal Connections
  Signal Connections:
    None
Nodes
. ( res://models/platform.glb)

Changed Properties:
None

./platform2#StaticBody3D (StaticBody3D)

Changed Properties:
None

./platform2#StaticBody3D/platform2_StaticBody3D#CollisionShape3D (CollisionShape3D)

Changed Properties:

  shape = res://objects/platform.tscn::ConcavePolygonShape3D_hyw7p
res://objects/platform_falling.tscn
Scene Tree
platform-falling ( res://models/platform-falling.glb)
  Area3D (Area3D)
    CollisionShape3D (CollisionShape3D)
  platform-falling2#StaticBody3D (StaticBody3D)
    platform-falling2_StaticBody3D#CollisionShape3D (CollisionShape3D)
Signal Connections
  Signal Connections:
    Area3D.body_entered -> .._on_body_entered (Flags: PERSIST)
Nodes
. ( res://models/platform-falling.glb)

Script: res://objects/platform_falling.gd
Changed Properties:
None

./Area3D (Area3D)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (0, 0.6, 0)]
./Area3D/CollisionShape3D (CollisionShape3D)

Changed Properties:

  shape = res://objects/platform_falling.tscn::BoxShape3D_t551e
./platform-falling2#StaticBody3D (StaticBody3D)

Changed Properties:
None

./platform-falling2#StaticBody3D/platform-falling2_StaticBody3D#CollisionShape3D (CollisionShape3D)

Changed Properties:

  shape = res://objects/platform_falling.tscn::ConcavePolygonShape3D_4mmvt
res://objects/platform_grass_large_round.tscn
Scene Tree
platform-grass-large-round ( res://models/platform-grass-large-round.glb)
  platform-grass-large-round2#grass-small ( res://models/grass-small.glb)
  platform-grass-large-round2#grass ( res://models/grass.glb)
  platform-grass-large-round2#grass2 ( res://models/grass.glb)
  platform-grass-large-round2#StaticBody3D (StaticBody3D)
    platform-grass-large-round2_StaticBody3D#CollisionShape3D (CollisionShape3D)
Signal Connections
  Signal Connections:
    None
Nodes
. ( res://models/platform-grass-large-round.glb)

Changed Properties:
None

./platform-grass-large-round2#grass-small ( res://models/grass-small.glb)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (-1.2632, 0.490424, 1.54658)]
./platform-grass-large-round2#grass ( res://models/grass.glb)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (1.38911, 0.443581, 1.45133)]
./platform-grass-large-round2#grass2 ( res://models/grass.glb)

Changed Properties:

  transform = [X: (-0.403434, 0, -0.915009), Y: (0, 1, 0), Z: (0.915009, 0, -0.403434), O: (0.907642, 0.443581, -1.67143)]
./platform-grass-large-round2#StaticBody3D (StaticBody3D)

Changed Properties:
None

./platform-grass-large-round2#StaticBody3D/platform-grass-large-round2_StaticBody3D#CollisionShape3D (CollisionShape3D)

Changed Properties:

  shape = res://objects/platform_grass_large_round.tscn::ConcavePolygonShape3D_xh0ma
res://objects/platform_medium.tscn
Scene Tree
platform-medium ( res://models/platform-medium.glb)
  platform-medium2#StaticBody3D (StaticBody3D)
    platform-medium2_StaticBody3D#CollisionShape3D (CollisionShape3D)
Signal Connections
  Signal Connections:
    None
Nodes
. ( res://models/platform-medium.glb)

Changed Properties:
None

./platform-medium2#StaticBody3D (StaticBody3D)

Changed Properties:
None

./platform-medium2#StaticBody3D/platform-medium2_StaticBody3D#CollisionShape3D (CollisionShape3D)

Changed Properties:

  shape = res://objects/platform_medium.tscn::ConcavePolygonShape3D_gwolp
res://objects/player.tscn
Scene Tree
Player (CharacterBody3D)
  Collider (CollisionShape3D)
  Character ( res://objects/character.tscn)
  Shadow (Decal)
  ParticlesTrail (CPUParticles3D)
  SoundFootsteps (AudioStreamPlayer)
Signal Connections
  Signal Connections:
    None
Nodes
. (CharacterBody3D)

Script: res://scripts/player.gd
Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (0, 0.5, 0)]
./Collider (CollisionShape3D)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (0, 0.55, 0)]
  shape = res://objects/player.tscn::CapsuleShape3D_gdq8c
./Character ( res://objects/character.tscn)

Changed Properties:
None

./Shadow (Decal)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (0, -0.9, 0)]
  size = (1, 2, 1)
  texture_albedo = res://sprites/blob_shadow.png
  modulate = (1, 1, 1, 0.7059)
  normal_fade = 0.5
./ParticlesTrail (CPUParticles3D)

Changed Properties:

  material_override = res://objects/player.tscn::StandardMaterial3D_q7stj
  cast_shadow = 0
  amount = 60
  mesh = res://meshes/dust.res
  emission_shape = 1
  emission_sphere_radius = 0.2
  particle_flag_align_y = true
  direction = (0, 0, 0)
  gravity = (0, 0.1, 0)
  scale_amount_min = 0.75
  scale_amount_curve = res://objects/player.tscn::Curve_xh1e2
./SoundFootsteps (AudioStreamPlayer)

Changed Properties:

  stream = res://sounds/walking.ogg
  volume_db = -5
  pitch_scale = 1.25
  autoplay = true
res://scenes/main.tscn
Scene Tree
Main (Node3D)
  Environment (WorldEnvironment)
  Player ( res://objects/player.tscn)
  View (Node3D)
    Camera (Camera3D)
  World (Node3D)
    platform ( res://objects/platform.tscn)
    platform4 ( res://objects/platform.tscn)
    platform2 ( res://objects/platform.tscn)
    platform3 ( res://objects/platform.tscn)
    platform-medium ( res://objects/platform_medium.tscn)
    platform-medium2 ( res://objects/platform_medium.tscn)
    platform-medium4 ( res://objects/platform_medium.tscn)
    platform-medium3 ( res://objects/platform_medium.tscn)
    platform-falling ( res://objects/platform_falling.tscn)
    platform-falling2 ( res://objects/platform_falling.tscn)
    platform-falling3 ( res://objects/platform_falling.tscn)
    platform-grass-large-round ( res://objects/platform_grass_large_round.tscn)
    flag ( res://models/flag.glb)
    coin ( res://objects/coin.tscn)
    coin10 ( res://objects/coin.tscn)
    coin2 ( res://objects/coin.tscn)
    coin3 ( res://objects/coin.tscn)
    coin5 ( res://objects/coin.tscn)
    coin6 ( res://objects/coin.tscn)
    coin7 ( res://objects/coin.tscn)
    coin8 ( res://objects/coin.tscn)
    coin9 ( res://objects/coin.tscn)
    coin4 ( res://objects/coin.tscn)
    cube8 ( res://objects/cloud.tscn)
    cube9 ( res://objects/cloud.tscn)
    cube10 ( res://objects/cloud.tscn)
    cube11 ( res://objects/cloud.tscn)
    cube12 ( res://objects/cloud.tscn)
    cube13 ( res://objects/cloud.tscn)
    cube14 ( res://objects/cloud.tscn)
  Sun (DirectionalLight3D)
  HUD (CanvasLayer)
    Icon (TextureRect)
    x (Label)
    Coins (Label)
Signal Connections
  Signal Connections:
    Player.coin_collected -> HUD._on_coin_collected (Flags: PERSIST)
Nodes
. (Node3D)

Changed Properties:
None

./Environment (WorldEnvironment)

Changed Properties:

  environment = res://scenes/main-environment.tres
./Player ( res://objects/player.tscn)

Changed Properties:

  view = ../View
./View (Node3D)

Script: res://scripts/view.gd
Changed Properties:

  transform = [X: (0.707107, 0, -0.707107), Y: (-0.298836, 0.906308, -0.298836), Z: (0.640856, 0.422618, 0.640856), O: (0, 0, 0)]
  target = ../Player
./View/Camera (Camera3D)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (0, 0, 10)]
  current = true
  fov = 40
./World (Node3D)

Changed Properties:
None

./World/platform ( res://objects/platform.tscn)

Changed Properties:

  transform = [X: (0.993085, 0, 0.117399), Y: (0, 1, 0), Z: (-0.117399, 0, 0.993085), O: (0, 0, 0)]
./World/platform4 ( res://objects/platform.tscn)

Changed Properties:

  transform = [X: (0.993085, 0, 0.117399), Y: (0, 1, 0), Z: (-0.117399, 0, 0.993085), O: (-15, 0, 4)]
./World/platform2 ( res://objects/platform.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (-3, 2, -3)]
./World/platform3 ( res://objects/platform.tscn)

Changed Properties:

  transform = [X: (0.966237, 0, 0.257656), Y: (0, 1, 0), Z: (-0.257656, 0, 0.966237), O: (-3, 3, -5)]
./World/platform-medium ( res://objects/platform_medium.tscn)

Changed Properties:

  transform = [X: (0.996134, 0, -0.087851), Y: (0, 1, 0), Z: (0.087851, 0, 0.996134), O: (-3, 0, 0)]
./World/platform-medium2 ( res://objects/platform_medium.tscn)

Changed Properties:

  transform = [X: (0.995121, 0, -0.09866), Y: (0, 1, 0), Z: (0.09866, 0, 0.995121), O: (-5, 0, 4)]
./World/platform-medium4 ( res://objects/platform_medium.tscn)

Changed Properties:

  transform = [X: (0.929796, 0, 0.368076), Y: (0, 1, 0), Z: (-0.368076, 0, 0.929796), O: (-14.9422, 0.991941, 0.128304)]
./World/platform-medium3 ( res://objects/platform_medium.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (0, 3, -6)]
./World/platform-falling ( res://objects/platform_falling.tscn)

Changed Properties:

  transform = [X: (0.984808, 0, -0.173648), Y: (0, 1, 0), Z: (0.173648, 0, 0.984808), O: (-9, 0.419294, 4)]
./World/platform-falling2 ( res://objects/platform_falling.tscn)

Changed Properties:

  transform = [X: (0.994522, 0, 0.104528), Y: (0, 1, 0), Z: (-0.104528, 0, 0.994522), O: (-12, -0.315063, 4)]
./World/platform-falling3 ( res://objects/platform_falling.tscn)

Changed Properties:

  transform = [X: (0.939693, 0, -0.34202), Y: (0, 1, 0), Z: (0.34202, 0, 0.939693), O: (-11.7527, 1.8303, -2.30579)]
./World/platform-grass-large-round ( res://objects/platform_grass_large_round.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (-7, 1, -2)]
./World/flag ( res://models/flag.glb)

Changed Properties:

  transform = [X: (0.707107, 0, 0.707107), Y: (0, 1, 0), Z: (-0.707107, 0, 0.707107), O: (0, 3.48077, -6)]
./World/coin ( res://objects/coin.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (-3, 0.635, 0)]
./World/coin10 ( res://objects/coin.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (-5, 0.635, 4)]
./World/coin2 ( res://objects/coin.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (-7.0437, 1.97005, -0.33003)]
./World/coin3 ( res://objects/coin.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (-7.0437, 1.97005, -1.33003)]
./World/coin5 ( res://objects/coin.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (-11.7731, 2.54941, -2.28223)]
./World/coin6 ( res://objects/coin.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (-14.8111, 1.6888, 0.328574)]
./World/coin7 ( res://objects/coin.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (-14.8111, 2.6888, 0.328574)]
./World/coin8 ( res://objects/coin.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (-14.9647, 0.801836, 3.99354)]
./World/coin9 ( res://objects/coin.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (0, 5, -6)]
./World/coin4 ( res://objects/coin.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (-7.0437, 1.97005, -2.33003)]
./World/cube8 ( res://objects/cloud.tscn)

Changed Properties:

  transform = [X: (1, 0, 0), Y: (0, 1, 0), Z: (0, 0, 1), O: (1.5495, 1.10741, -2.666)]
./World/cube9 ( res://objects/cloud.tscn)

Changed Properties:

  transform = [X: (1.27593, 0.471408, -0.343721), Y: (-0.401864, 1.30937, 0.304009), Z: (0.422933, -0.178025, 1.32582), O: (3.33538, 1.37146, -4.1932)]
./World/cube10 ( res://objects/cloud.tscn)

Changed Properties:

  transform = [X: (1.32811, -0.293866, -0.34372), Y: (0.370441, 1.3186, 0.30401), Z: (0.259369, -0.37854, 1.32582), O: (-10.5752, 2.03819, -7.93707)]
./World/cube11 ( res://objects/cloud.tscn)

Changed Properties:

  transform = [X: (0.476646, -0.929853, -0.93624), Y: (0.924607, 0.945559, -0.468385), Z: (0.941422, -0.457882, 0.934042), O: (-11.1815, 2.03819, 9.2812)]
./World/cube12 ( res://objects/cloud.tscn)

Changed Properties:

  transform = [X: (-1.02876, -0.929853, -0.213027), Y: (-0.695523, 0.945557, -0.768461), Z: (0.652886, -0.457881, -1.15432), O: (-10.9158, 2.79508, 11.515)]
./World/cube13 ( res://objects/cloud.tscn)

Changed Properties:

  transform = [X: (1.56209, 1.97375, -0.974547), Y: (-1.37982, 1.80907, 1.4522), Z: (1.71508, -0.342241, 2.05595), O: (-14.3045, 2.03819, -8.24191)]
./World/cube14 ( res://objects/cloud.tscn)

Changed Properties:

  transform = [X: (1.56209, 1.97375, -0.974547), Y: (-1.37982, 1.80907, 1.4522), Z: (1.71508, -0.342241, 2.05595), O: (-15.866, 2.03819, 7.83702)]
./Sun (DirectionalLight3D)

Changed Properties:

  transform = [X: (-0.422618, 0, -0.906308), Y: (-0.694272, 0.642788, 0.323744), Z: (0.582563, 0.766044, -0.271654), O: (0, 0, 0)]
  shadow_enabled = true
  shadow_opacity = 0.75
./HUD (CanvasLayer)

Script: res://scripts/hud.gd
Changed Properties:
None

./HUD/Icon (TextureRect)

Changed Properties:

  offset_left = 57
  offset_top = 67
  offset_right = 313
  offset_bottom = 323
  scale = (0.2, 0.2)
  texture = res://sprites/coin.png
./HUD/x (Label)

Changed Properties:

  offset_left = 112
  offset_top = 64
  offset_right = 144
  offset_bottom = 123
  text = ×
  label_settings = res://scenes/main.tscn::LabelSettings_38ys3
./HUD/Coins (Label)

Changed Properties:

  offset_left = 144
  offset_top = 64
  offset_right = 368
  offset_bottom = 123
  text = 0
  label_settings = res://scenes/main.tscn::LabelSettings_38ys3

Scripts

res://objects/cloud.gd
extends Node3D

var time = 0.0

var random_number = RandomNumberGenerator.new()

var random_velocity:float
var random_time:float

func _ready():
	
	random_velocity = random_number.randf_range(0.1, 2.0)
	random_time = random_number.randf_range(0.1, 2.0)

func _process(delta):
	
	position.y += (cos(time * random_time) * random_velocity) * delta # Sine movement
	
	time += delta

res://objects/coin.gd
extends Area3D

var time := 0.0
var grabbed := false

# Collecting coins

func _on_body_entered(body):
	if body.has_method("collect_coin") and !grabbed:
		
		body.collect_coin()
		
		Audio.play("res://sounds/coin.ogg") # Play sound
		
		$Mesh.queue_free() # Make invisible
		$Particles.emitting = false # Stop emitting stars
		
		grabbed = true

# Rotating, animating up and down

func _process(delta):
	
	rotate_y(2 * delta) # Rotation
	position.y += (cos(time * 5) * 1) * delta # Sine movement
	
	time += delta

res://objects/platform_falling.gd
extends Node3D

var falling := false
var gravity := 0.0

func _process(delta):
	scale = scale.lerp(Vector3(1, 1, 1), delta * 10) # Animate scale
	
	position.y -= gravity * delta
	
	if position.y < -10:
		queue_free() # Remove platform if below threshold
	
	if falling:
		gravity += 0.25


func _on_body_entered(_body):
	if !falling:
		Audio.play("res://sounds/fall.ogg") # Play sound
		scale = Vector3(1.25, 1, 1.25) # Animate scale
		
	falling = true

res://scripts/player.gd
extends CharacterBody3D

signal coin_collected

@export_subgroup("Components")
@export var view: Node3D

@export_subgroup("Properties")
@export var movement_speed = 250
@export var jump_strength = 7

var movement_velocity: Vector3
var rotation_direction: float
var gravity = 0

var previously_floored = false

var jump_single = true
var jump_double = true

var coins = 0

@onready var particles_trail = $ParticlesTrail
@onready var sound_footsteps = $SoundFootsteps
@onready var model = $Character
@onready var animation = $Character/AnimationPlayer

# Functions

func _physics_process(delta):

	# Handle functions

	handle_controls(delta)
	handle_gravity(delta)

	handle_effects(delta)

	# Movement

	var applied_velocity: Vector3

	applied_velocity = velocity.lerp(movement_velocity, delta * 10)
	applied_velocity.y = -gravity

	velocity = applied_velocity
	move_and_slide()

	# Rotation

	if Vector2(velocity.z, velocity.x).length() > 0:
		rotation_direction = Vector2(velocity.z, velocity.x).angle()

	rotation.y = lerp_angle(rotation.y, rotation_direction, delta * 10)

	# Falling/respawning

	if position.y < -10:
		get_tree().reload_current_scene()

	# Animation for scale (jumping and landing)

	model.scale = model.scale.lerp(Vector3(1, 1, 1), delta * 10)

	# Animation when landing

	if is_on_floor() and gravity > 2 and !previously_floored:
		model.scale = Vector3(1.25, 0.75, 1.25)
		Audio.play("res://sounds/land.ogg")

	previously_floored = is_on_floor()

# Handle animation(s)

func handle_effects(delta):

	particles_trail.emitting = false
	sound_footsteps.stream_paused = true

	if is_on_floor():
		var horizontal_velocity = Vector2(velocity.x, velocity.z)
		var speed_factor = horizontal_velocity.length() / movement_speed / delta
		if speed_factor > 0.05:
			if animation.current_animation != "walk":
				animation.play("walk", 0.1)

			if speed_factor > 0.3:
				sound_footsteps.stream_paused = false
				sound_footsteps.pitch_scale = speed_factor

			if speed_factor > 0.75:
				particles_trail.emitting = true

		elif animation.current_animation != "idle":
			animation.play("idle", 0.1)
	elif animation.current_animation != "jump":
		animation.play("jump", 0.1)

# Handle movement input

func handle_controls(delta):

	# Movement

	var input := Vector3.ZERO

	input.x = Input.get_axis("move_left", "move_right")
	input.z = Input.get_axis("move_forward", "move_back")

	input = input.rotated(Vector3.UP, view.rotation.y)

	if input.length() > 1:
		input = input.normalized()

	movement_velocity = input * movement_speed * delta

	# Jumping

	if Input.is_action_just_pressed("jump"):

		if jump_single or jump_double:
			jump()

# Handle gravity

func handle_gravity(delta):

	gravity += 25 * delta

	if gravity > 0 and is_on_floor():

		jump_single = true
		gravity = 0

# Jumping

func jump():

	Audio.play("res://sounds/jump.ogg")

	gravity = -jump_strength

	model.scale = Vector3(0.5, 1.5, 0.5)

	if jump_single:
		jump_single = false;
		jump_double = true;
	else:
		jump_double = false;

# Collecting coins

func collect_coin():

	coins += 1

	coin_collected.emit(coins)

res://scripts/view.gd
extends Node3D

@export_group("Properties")
@export var target: Node

@export_group("Zoom")
@export var zoom_minimum = 16
@export var zoom_maximum = 4
@export var zoom_speed = 10

@export_group("Rotation")
@export var rotation_speed = 120

var camera_rotation:Vector3
var zoom = 10

@onready var camera = $Camera

func _ready():
	
	camera_rotation = rotation_degrees # Initial rotation
	
	pass

func _physics_process(delta):
	
	# Set position and rotation to targets
	
	self.position = self.position.lerp(target.position, delta * 4)
	rotation_degrees = rotation_degrees.lerp(camera_rotation, delta * 6)
	
	camera.position = camera.position.lerp(Vector3(0, 0, zoom), 8 * delta)
	
	handle_input(delta)

# Handle input

func handle_input(delta):
	
	# Rotation
	
	var input := Vector3.ZERO
	
	input.y = Input.get_axis("camera_left", "camera_right")
	input.x = Input.get_axis("camera_up", "camera_down")
	
	camera_rotation += input.limit_length(1.0) * rotation_speed * delta
	camera_rotation.x = clamp(camera_rotation.x, -80, -10)
	
	# Zooming
	
	zoom += Input.get_axis("zoom_in", "zoom_out") * zoom_speed * delta
	zoom = clamp(zoom, zoom_maximum, zoom_minimum)

res://scripts/hud.gd
extends CanvasLayer

func _on_coin_collected(coins):
	
	$Coins.text = str(coins)

res://scripts/audio.gd

Autoload: Audio (disabled)

extends Node

# Code adapted from KidsCanCode

var num_players = 12
var bus = "master"

var available = []  # The available players.
var queue = []  # The queue of sounds to play.

func _ready():

	for i in num_players:
		var p = AudioStreamPlayer.new()
		add_child(p)
		
		available.append(p)
		
		p.volume_db = -10
		p.finished.connect(_on_stream_finished.bind(p))
		p.bus = bus


func _on_stream_finished(stream): available.append(stream)

func play(sound_path): queue.append(sound_path)

func _process(_delta):

	if not queue.is_empty() and not available.is_empty():
		
		available[0].stream = load(queue.pop_front())
		available[0].play()
		available[0].pitch_scale = randf_range(0.9, 1.1)
		
		available.pop_front()

Resources

res://objects/player.tscn::CapsuleShape3D_gdq8c

Type: CapsuleShape3D

Changed Properties:

  radius: 0.30000001192093
  height: 1
res://sprites/blob_shadow.png

Type: CompressedTexture2D

Changed Properties:

  load_path: res://.godot/imported/blob_shadow.png-d19f4ffceb1d99dd3331acec2dc6d7df.ctex
res://objects/player.tscn::StandardMaterial3D_q7stj

Type: StandardMaterial3D

Changed Properties:

  diffuse_mode: 2
  specular_mode: 2
  metallic_specular: 0
  backlight: (0, 0.5216, 0.7098, 1)
  billboard_keep_scale: true
  grow_amount: 1.88199996948242
  proximity_fade_distance: 0.25

Shaders

@gertkeno @FencerDevLog @sirlich

I am curious for your feedback on this.

Edit: it adds a menu option under tools to run it

My goal is to make a tool that would help new users with small projects make posts here that have more complete information about their project so they can be more easily helped.

I think works pretty well, but will definitely need some work.

I think it could be helpful on larger projects as well, but would need some more flexibility picking out which parts of a project to document. As of right now, a large project would just be waaaay to much to post everything. Even Kenneys starter had to be trimmed to fit in a post.

If you have some small toy project, I’d like you to run it and provide some feedback.

I have found myself using it some for personal use as it prints out a list of only settings and properties that have changed. So I can scan through a scene really quickly and see all the non-default settings.

1 Like

Really nice job with the plugin!

I definitely like how the you’ve also listed out the project settings and only included the changed variables for each Node.

It would be nice to have the Node Type listed next to each node in the tree.

Or have the option to include the functions from any nodes that have a script.

Will have to give this a try when I get home :grin:

1 Like

I haven’t tried it yet, but it looks very interesting. And it’s true that many new Godot users tend to have trouble sharing similar information, so something like this could be quite useful in the early stages of development when the project size hasn’t grown too much yet. Good job!

1 Like

It should show the node types (and does for most) but I have introduced a bug when I tried to add optional limits to the scope via excluding folders (currently it just doesnt scan that folder for scenes or resource details, but that causes some issues).

It should show what script a node has and then document that script at the end, or did ypu have something else in mind?

I am rethinking how to limit the scope as follows:

  1. choose which folders to scan for scenes
  2. select which scenes to document
  3. optionally deselect specific nodes, resources, and scripts found in those scenes
1 Like