Note : Godot 3.2.3, Blender 2.83, Gimp 2.10.18.
January wasn't a good month for game development. I felt tired and scatterbrained. Maybe I overdid it a bit towards the end of 2020. Or maybe the state of the world has been getting to me ...
Anyway. I decided to start February with some work on gameplay.
So, I fired up the game and spent some time walking around in the start area.
After a while, I figured out how I want things to work.
And one of those things included cloth.
I definitely wanted to Unveil Something.
Having absolutely no clue on how to go about doing that, I do what I always do : I start looking
for tutorials (see bottom of page).
The first tutorials I came across were Unity-specific and mentioned a Cloth component. But, as it turns out, Godot has something similar : the SoftBody node.
My test scene setup consist of a SoftBody (plane mesh) and an object that I want to cover up.
When you add a SoftBody node to the scene, Godot will complain that it needs a
mesh to work with. This mesh can be something you modeled in eg. Blender, or it can be
a Godot primitive (new PlaneMesh ; I used 20 subdivisions).
Godot then marks all vertices of the mesh with a red dot, to indicate that they are now part of a physics system. As always : more verts equals more detail, but also requires more processing power.
And that's it, really.
Run the scene ... and enjoy the show.
Or not. 🙀
The cloth seems to go right through the collision shape of the object that I'm trying to cover.
I tried a couple of different collision shapes, like a fatter box (but that doesn't look good because it doesn't match the shape of the object) and a horizontal capsule. It sort-of-almost worked, but ...
To stop the cloth from falling off, I tried 2 different approaches : pinning, and friction.
The idea behind 'friction' is that I wanted to make the covered object 'less slippery' by
adding a physics material to its StaticBody.
The default/allowed settings didn't seem to make much of a difference. So, this idea was a big, fat fail.
'Pinning' is useful for things like flags or clothes hanging from a hook on a wall. You basically specify which vertices the physics engine is not allowed to move.
This is how you set it up :
With the SoftBody node selected click the vertices you want to pin. If you succeed, the vertices will turn blue.
The vertex selection procedure seems a bit wonky at first, but what you need to do, is
click the vert that you want to pin, release the mouse, and move off the vert. It will
now turn blue. To see the updated contents of the array with pinned verts, you need
to click where it says 'PoolIntArray' (it doesn't seem to auto-update).
As an aside, note that the pinned verts also show up in the 'attachments' section, just below 'pinnend points'. I'm not sure how this is supposed to be used though.
The combination of the capsule collision shape and some pinned verts wasn't too bad (and for very little effort) :
I'm sure I could use an AnimationPlayer to unpin the verts when the player interacts with the cloth ... But I have no idea how to make the cloth fall off.
In conclusion : unless I can figure out how to apply some force to the cloth when the player is interacting with it, the Godot SoftBody approach isn't going to work for me. I think it is probably meant to be used for for capes and flags and such.
Another thing with this approach is that the cloth mesh is sometimes intersecting with itself. I'm not sure if this can easily be prevented.
The second type of tutorials I came across were about doing 'a cloth simulation' in Blender.
And they terrified me.
But ... after 2 days of research and experimentation, I managed to come up with this :
I'm sure there are many things that could be done better, but to me it looks simply amazing. 😻
And this is how I did it :
This is a simple scene with a cloth and the object that I want to drape the cloth on.
You may also want to place a floor and/or walls, if you need to limit the movement of the cloth
to a certain area.
It's a good idea to position the 'object' at (0,0,0), and 'apply rotation, scale, and position' to the object and the cloth.
The 'cloth' is simply a subdivided plane.
More subdivisions will result in finer detail in the draped cloth, but also a higher number of verts and a bigger file size. See (*) a bit further down the text.
All objects that will interact with the cloth (floor, walls, object you want to drape the cloth on) need to have a 'collision' modifier (physics properties panel). The cloth (plane) needs to have the 'cloth' modifier (below the 'collision' button) :
There are many settings for the cloth modifier, but I found it easiest to just pick
one of presets.
You also need to check the 'self collisions' option so that the cloth doesn't intersect with itself.
Now, if all is well, you should be able to start the cloth sim by pressing the 'play'
button from the timeline.
You can adjust the 'end' frame setting to your liking.
(*) Note : To check if you have subdivided the cloth plane enough times (but not too many times), add a subdivision surface modifier to the modifier stack (it should be below the cloth modifier) and set the cloth shading to smooth. If the draped cloth still looks voxelated (is that a word ?), subdivide the cloth plane once more and try again.
If you are happy with what you are seeing, it may be time to 'bake' the animation to the cache (make sure to disable/ remove the subdivision surface modifier first !)
Make sure the timeline is set to frame 0 before you press the 'bake' button. Also, make sure
the 'end' frame is set to an appropriate value. There is no need to bake 240 frames, if your
animation is finished after 100 frames ...
If you need to re-bake after having made additional changes, you will need to 'delete all bakes' first.
For most projects, the sim 'bit' is now over, and you can continue to the 'cleanup and export'.
In my particular case, this sim is only the first part. I want to use the endpoint of the first simulation as the starting point for a second simulation.
I'm not sure what the best way is to 'freeze' the cloth into a position you like, but I've found 2 ways that seem to work. You may want to make a copy of the blend file before you do this, so you don't lose the info of the 1st cloth sim.
Method 1 :
Scroll to the timeline frame you like to use as the start point for the second sim. Go to the 'modifier' tab and press 'apply as shape key'. The cloth now 'remembers' 2 shapes : the original plane, and the 'draped' shape.
Next, switch to the 'object data properties' tab and set the 'cloth value' to 1.
If you now check the 'modifier' tab again, you will see that the cloth has a 'key' set, but it no longer has the cloth modifier. The cloth is now ready to be used in a new sim (*).
(*) Be careful when using this method : once a mesh
has a shape key, you can no longer 'apply' a subdivision surface modifier !
In other words, you need to add the subsurf modifier first, then apply it, and lastly get rid of the cloth modifier (apply as shape key). This will increase the vert count in the mesh, so the second sim might become very slow !
Method 2 :
If you have made a backup of the original simulation, you might as well use the 'apply' button in the modifier tab (make sure you're on the correct frame in the timeline !). The cloth now only remembers this one, final shape.
I want to limit the cloth movement in the 2nd sim (because of where I will place the cloth-covered object in the game), and so, I've put up 2 walls (*).
The walls, the floor, and the object once again get a 'collision' modifier in the physics tab. The cloth gets a new 'cloth' modifier.
(*) If the cloth starts behaving unexpectedly, check if the wall/ floor plane collision modifier is set to single sided. If so, check if the normals are pointing in the right direction (show overlays > face orientation).
And now for the hardest bit : pulling the cloth from the object ...
Select the cloth and go into edit mode. Select a small number of vertices in the area
where you want to initiate the pulling motion. With the verts selected, press Ctrl+G (assign
to new group). Switch to the 'object data properties' tab and inspect the 'vertex groups'.
You should see a group there. Double click to change its name (optionally) eg. to 'pull'.
Check that all is well by clicking 'deselect' and 'select'. The verts should get selected again on the mesh.
Go back into object mode and switch to the physics tab. Scroll down to the 'shape' section
and assign the vertex group you just created to the 'pin group'.
Do not forget to also check the 'self collisions' option.
I also re-applied rotation, scale, and location.
Next, add an armature to the scene and orient it in a way that makes it convenient to animate the pulling motion.
Finally, select the cloth, shift select the bone, and press Ctrl+P (parent : 'armature deform with
automatic weights') (*).
To check that all went well, select the cloth and switch over to the 'object properties' tab. The 'relations' section should show 'armature' as the parent .
(*) Switch over to the modifier tab and check that the armature modifier is on top of the cloth modifier ! We want the cloth to follow the movement of the bone !
Now, it's time to keyframe the movement of the bone.
So, select the bone, go to the 1st frame in the timeline, move the mouse to the location and rotation pannel (don't click) and press 'I' (insert keyframe). The sections turn yellow.
Go to a new frame on the timeline, move the bone a little bit (translation / rotation) and press 'I' again when the mouse is over the location and rotation panel.
Continue until the movement is completely done and bake the animation.
If you need to adjust the movement, just overwrite the data (by pressing 'I' again). You can also box-select keyframes on the timeline and move them around (press 'G' for grab), or delete them.
This is what my timeline animation looks like for the bone :
Go to the 1st frame on the timeline and start the bake (still without active subsurf modifier).
There. All done.
The next problem is now how to get the simulation data (animation) into Godot ...
I couldn't find much information on this step, but apparently, what you want to do is convert the
data from the cache (bake) into keyframes with shapekeys.
For that, you need to activate the 'mdd' add-on in Blender (edit > preferences).
Select the cloth, go to 'file' > 'export' > 'Lightwave Point Cache (mdd)' (*).
As my animation seems to be finished around frame 88, I set the end frame to 88 (no need to export more than you need).
Now is another good time to make a backup of your blend file (in case you need it later).
(*) Important :
If at this point, your cloth mesh looks 'voxelated' and needs a subsurf modifier (+ shade smooth), you need to add and apply it -before- you export to mdd ! The number of vertices that are exported to mdd needs to be exactly the same as the number of verts in the mesh that will receive the mdd data.
Also, you cannot add the subsurf modif -after- the mdd import, because Blender cannot apply a subsurf modifier to a mesh that has shape keys !
Furthermore, exporting a mesh with shape keys and an unapplied subsurf modifier (with 'apply modifiers' checked during export to eg. gltf) will result in an error when you try to import the gltf file into Godot !
Before importing the mdd data back into your Blender project, you need to cleanup the cloth object.
Select the cloth and press Alt+P (clear parent and keep transform). You can now safely delete the 'armature' modifier from the modifier stack. You can also delete the armature from the scene.
Switch to the physics tab and delete the cloth modifier.
We're now back at where we started the 2nd simulation.
Select the cloth and go to 'file' > 'import' > 'mdd'. Select the file
you just created.
You should now have a timeline with a whole bunch of keyframes ... and everything should still work when you scrub the timeline !
If you want to reduce the number of keyframes for your animation, or if you want to
tweak it, you can switch over to the 'animation' workspace. You can use both the 'dope sheet'
editor and the 'shape key' editor (which you find by
first going to the dope sheet editor, and then, from the dropbox where it says 'dope sheet',
select 'shape key editor'.
Or, you can do some limited editing directly from the timeline.
Once you're completely happy with your animation, select the cloth and export as 'gltf'. These are the settings I use (not sure if these are correct, but they work) :
If you import the gltf file in Godot, you will end up with a cloth object and an AnimationPlayer.
You can find all the keyframes and shape keys (and tweak them) in both the property inspector with the cloth selected, and in the AnimationPlayer :
And that's that.
You now have a cloth animation in your game !
Godot imports animations at 15 fps by default ! So, you may want to re-import
the animation at 24 fps (if that's what you used in Blender) (*).
Also, notice that Godot 'optimizes' the animation on import. If this does not give a good result, you may want to play with these settings, or even turn them off.
To actually play the animation at 24 fps, you also need to set the fps at the very bottom of the AnimationPlayer (a little bit confusing) !
My animated cloth is huge (lots of verts and lots of keyframes). My plan is to replace the cloth with a lower poly static version as soon as the player has finished interacting with it.
It wasn't immediately clear to me, how I could get eg. the cloth shape from keyframe 64
and get rid of all the shape keys.
This is how I finally accomplished it (but maybe there's a better way) :
Step 1 : Delete all unwanted keyframes from the timeline
(I kept only frame 64).
Box-select the keyframes (selected = yellow) > press 'x' > delete keyframes.
Step 2 : Delete all unwanted shape keys ; make sure -not- to
delete 'basis' (since all shapes are relative to that one).
Switch to the 'object data properties' tab with the cloth selected > press the '-' button to remove shape keys (one by one).
Step 3 : Remove the last shape keys by first creating a new one.
With the last shape key selected, press the 'shape key specials' button (the darker button just below the '-' key) and select 'new shape from mix'. Now delete the shape key (63 in my case), next remove 'basis', and finally remove the shape key you just created (the new shape key has to be deleted last !).
You can now also delete the last keyframe on the timeline.
To reduce the vert count, I used a 'decimate' modifier with the 'collapse' option and a ratio set to 0.1.