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 checkslerp_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
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.
Multiplayer
@rpc annotations:@rpc("call_local", "any_peer", "reliable") to call method on all peers from any peer.
@rpc("call_remote", "any_peer", "reliable") - rpc_id(1, "methodname") for any peer to call a server method
MultiplayerSynchronizer node to replicate it's variables from the authority to all others.
Might need to make a specific node/script just to hold vars for it, it has trouble directly accessing vars on some nodes, like CharacterBody3D.
MultiplayerSpawner node to replicate all children of a specified node from the authority to all others.
Has mysteriously failed on me, not sure if buggy or I don't know how to use it.
set_multiplayer_authority(name) where your name is set to your peer_id from the authority. Then each player can control their character, still need synchros
rpc's cannot return values, but you can do it with an extra rpc call:
client - player.gd Globals.main.level.rpc_id(1, "find_spawn") server - level.gd @rpc("call_local", "any_peer") func find_spawn(team_num := 0): var point := Vector3.INF ... var caller := multiplayer.get_remote_sender_id() Globals.main.players[caller].rpc_id(caller, "set_respawn_point", point) client - player.gd @rpc("call_local", "any_peer") func set_respawn_point(point): global_position = point
if you get tons of error spam about sync_state, try looking for MultiplayerSynchronizer's with no properties assigned.
You can calculate the distance from object2's plane (via their up-vector) by using dot-product:
var distance := abs(object2.global_transform.y.dot(object1.global_position))
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 on the physics object
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.
Debug -> Keep debug server open checkbox to listen and attach to other godot instances that run
Can set a constant color on a reflection probe for colored ambient light in an area
Mobile = lightmapgi and reflection probes, no fancier effects.
Faking GI here
To make a 3d thing invisible but still cast a shadow (like a fps player's head for example), just set each mesh.cast_shadow = GeometryInstance3D.SHADOW_CASTING_SETTING_SHADOWS_ONLY in code or find it in the editor. Alpha materials don't work.
Godot XR Tools - premade code and scenes to help get started on vr games faster.
if mouse clicks aren't getting through to 3d, check for ui nodes eating mouse input. Check their Mouse -> Filter and try changing it to Pass.
When saving resources you can set a custom name that you access with resource.resource_name - useful for comparing materials.