Tips for using the Godot game engine

Blender

Backface culling = material -> viewport display -> settings -> backface culling checkbox.

If collision is messed up, check the normals, apply scale (maybe all transforms), and recalc normals in Blender.

If animations messed up - reset all bone positions to rest before exporting from blender

GDScript

Casting:

  var button := node as Button
    if button:
      #it's this type! No need for comparisons or type checks
      
lerp_angle() for smoothly transistioning between angles

Hold alt for multi-caret editing

'"property" in node' to see if node.property exists

Uninitialized Strings are "" NOT null

In 'match' statements use vars only, expressions don't get evaluated

Do NOT save Callables in a Resource

Events.gd - a script with only signal declarations in it. Make it autoload so its a global singleton. Then hook up global events through it, very handy.

Misc

Use Area3D's to control audio buses, to get different reverb or effects for different areas.

Right click a scene -> view owners to see what uses that scene

For anisotropic filtering - need to enable on each material - set texture_filter as linear w/ mipmaps anisotropic

If your gui isn't expanding as expected, check container sizing and the 'expand' checkbox

Timer.start(time) - timer overwrites the earlier wait_time when called for all future calls too

Can add Timers to the scene to save on setup code and remembering to add_child() them

Custom values for instantiated scenes - Right click on node -> check Editable Children

Can add any data to any node using metadata in the editor or code

Unique Names - right click node in editor -> check % scene unique name then use in code like '%myNode'

Get 3d node's screen position - 'cam.unproject_position(node.get_global_position)'

Callable .bind() args are added after .call() args

Keep physics fps at or above fps otherwise there's a lotta jitter

Tweens work on bools and lots of other types, but not always in the expected way

linear_to_db() for volume sliders

get_instance_id() and instance_from_id() to get global references to any node.

gui in 3d -
 add a sub Viewport to a Sprite3D.
 give it a viewport texture in subviewport
 turn transparent BG on
 trim off bottom and right pixels with the sprite3d's region
 if using a meshinstance - material has to be local to scenes

Vector.distance_to_squared() is faster than Vector.distance_to() so use it when you can

Triplanar mapping and displacements maps can't work together

Small things ignoring collisions? Turn on continuous CD

Physics never sleep? might have to write own code to stop it at low vels

'F' in editor to zoom to select node

To move a rigid body via code, need to use _integrate_forces(state) and modify the state var:

  func _integrate_forces(state):
    if reset:
      reset = false
      state.transform = Transform2D(0.0, reset_pos)
      linear_velocity = Vector2.ZERO
      angular_velocity = randf_range(-4.0, 4.0)

If your subviewport looks blurry, change the texture filtering on the SubViewportContainer -> CanvasItem -> Texture -> Filter -> set to Nearest. Might need to turn on Stretch at the top too. Also might need code to resize the subviewport to the container's size on size_changed signal.

Overlapping Areas that have scripts with body_entered can be screwy. Separate them a bit.