3 min read

Baking Mesh Skeleton Poses in Godot 4.4

Baking Mesh Skeleton Poses in Godot 4.4

We're almost done with developing the environmental hazards and this last one proved a bit more difficult than anticipated. Thankfully, Godot 4.4 released a few days prior to starting the work on this [great timing], which had some additions that helped overcome the main issue.

The hazard being developed is the electric floor tiles, which if the player steps on will electrocute them. The original idea was to have a bit of fun with this one, and rather than have a generic damage effect applied to the player, instead freeze them in place and have them crumble into a pile of ashes.

As the player would be charred into a single colour, achieving the visual effect of the ashes falling could easily be achieved with a basic particle emitter; the challenge was getting those particles to spawn in a shape that represented the player.

Thankfully, Godot supports being able to create complex emission shapes (see This Page for more information), so it seemed this would be a rather easy task. Unfortunately, when using the method outlined in the documentation, the emission points it generates don't follow the surface of the deformed mesh (i.e. the way it is posed using a Skeleton3D). Instead, the generated emission points follow the surface of the mesh in its unposed state, like you can see here where the arms are posed upwards, but the emission points are generated as if the arm is by the player's side (i.e. how it is in its default pose):

A screenshot showing that the emission points of the particle emitter are not representative of the posed mesh

Had the poses been made in Blender, it would have been possible to export meshes in those poses, but the posing was done purely in Godot, so a solution to bake the pose into a new mesh within Godot was required.

Luckily, Godot 4.4 had just been released and within it was a new addition (see PR #85018) that provides this specific functionality! Huge shoutout to smix8 and the Godot team that tested and helped it get into this release; you are the MVPs.

There was unfortunately still one minor issue - the bake_mesh_from_current_skeleton_pose function isn't exposed in the GUI at all, and although this could be done at runtime theoretically, it would be runtime overhead that isn't necessary, given that in the case of this animation - we know what we want to be baked ahead of time.

Thankfully, it is pretty easy to create tool scripts in Godot, and so the functionality was implemented like this:

@tool
class_name MeshBaker
extends Node3D

@export_tool_button("Bake", "Callable") var bake_action: Callable = bake

@export_group("Settings")
@export var applied_scale: Vector3 = Vector3(1.0, 1.0, 1.0)
@export var source_meshes: Array[MeshInstance3D]


func bake() -> void:
	for mesh in source_meshes:
		var baked_mesh := ArrayMesh.new()
		mesh.bake_mesh_from_current_skeleton_pose(baked_mesh)

		var baked_name := mesh.name + "_Bake"
		var existing_node: Node = find_child(baked_name)

		if existing_node:
			remove_child(existing_node)

		var mesh_instance := MeshInstance3D.new()
		mesh_instance.name = baked_name
		mesh_instance.mesh = baked_mesh
		mesh_instance.scale = applied_scale
		mesh_instance.skeleton = NodePath("")

		add_child(mesh_instance)
		mesh_instance.owner = get_tree().edited_scene_root

The script allows for multiple meshes to be passed to it in the GUI so they can be baked and have the specified scale applied to them after clicking the "Bake" button. In this instance, the player consists of 6 separate meshes, so all 6 of these were assigned to the MeshBaker node like so:

A screenshot showing the setup of the mesh baker node

After clicking the bake button, we now have a baked copy of the posed meshes and they all appear as children of the MeshBaker node:

The posed skeleton and the baked mesh side by side
A screenshot displaying how the baked meshes are stored in the node tree

If anyone else is in the same boat of having their animations / poses exist exclusively in Godot, feel free to use this script in your own projects; hopefully it can help.

Although there isn't much that can be added to the script, any future versions / improvements of the script will be available on GitHub at https://github.com/FiveNineGames/godot-mesh-baker 🙂