Automate baking armature actions in python

Hi folks,

I am doing a python script to automatically bake all actions of the armature of a character, so I can export it to Unity engine. With baking I mean convert to keyframes the movements of the deforming bones, that was animated with bones controllers (constraints), and remove those constraints. The idea is to bake all the actions of the armature with a single button, and then export it as FBX with all actions and just the deforming bones (in Unity I don’t need the bones used as controller or helper).

I sort of finished that script, but for some reason it only works if there is just one action. It doesn’t work if there is more than one. In that case it seems to do everything but bake the keys, even it removes the constraints (which actually the same baking does), but there is no key in any of the animations.

The thing is that I am a very experienced programmer in C# language, but not in python. I have an idea what could be happening, but I’m not sure. Maybe it doesn’t bake any of the keys when there are more that one action because it needs some time to finish baking every action, and in every loop it doesn’t wait for that. Something like async methods in C# perhaps? I don’t even know if there is such a thing in python, or if the baking function is awatable.

Here is the script i am writing:

if bpy.data.actions and bpy.context.active_object:

        #Change to pose mode
        bpy.ops.object.mode_set(mode='POSE')
        
        #Select all the deforming bones, which are on layer 2
        bpy.context.object.data.layers[1] = True
        bones = [b for b in bpy.context.active_object.pose.bones if b.bone.layers[1]]
        
        bpy.ops.pose.select_all(action='DESELECT')
        for b in bones:
            b.bone.select=True


        #Loop in all actions
        for a in bpy.data.actions:
            
            if not a:
                continue
            
            bpy.context.active_object.animation_data.action = a
            
            firstFrame = 9999999
            lastFrame = -9999999
            
            #Get the first and last keyframes of the current action
            for fcu in a.fcurves:
                        for keyframe in fcu.keyframe_points:
                            
                            x, y = keyframe.co
                            k = math.ceil(x)
                            
                            if k < firstFrame:
                                firstFrame = k
                            
                            if k > lastFrame:
                                lastFrame = k
            
            #Bake it
            bpy.ops.nla.bake(frame_start=firstFrame, frame_end=lastFrame, only_selected=True, visual_keying=True, clear_constraints=True, use_current_action=True, bake_types={'POSE'})
            
            print ("Action: {}, First frame: {}, Second frame: {}".format(a.name, firstFrame, lastFrame))
            
    else:
        print ("There has to be at least an action and an object selected (with that action) to be able to perform the baking")

Here is a link so it’s easy to read: http://textuploader.com/58lxy
In the code I select all the bones from layer 2 (index 1) as that’s the layer where all the deforming bones are.

Any thoughts?

Edit: Actually, when there are more than one action, it only bakes properly the first one, but not the rest.

1 Like

I Just managed to make it work. It was just that in the first loop, after baking, it removed all the constraints from the deforming bones, so for the next loops they didn’t have any moves (as all constraints were removed).
Thanx anyway

2 Likes