6
$\begingroup$

I would like to share animations sequences between models (if possible).

There are currently several models and more will be added soon. All of the models need to execute the same animation sequences like walk, run, fight, etc. These animations will be seen from different camera angles since they will be used in an isometric game.

I would like to automate the build process. Is it possible to link an in-house 'standard' armature (set of bones) and make all of the artists bind different meshes to the same rig, and then animate the standard rig?

I know that it would limit the artists since they would be forced to fit the models they make to the rig, but I hope it would give us the ability create more animations quickly and at lower cost than using custom animations. Is this possible?

$\endgroup$
2
  • $\begingroup$ i dont feel qualified to mark an answer as correct since I'm going to have to sit for several hours to try each out. if the community agrees on a specific solution +ing it up then i will mark that as the correct answer. otherwise, I'm going to have to wait until I can test. $\endgroup$ Commented May 21, 2014 at 1:39
  • $\begingroup$ Do you still need more time to try out the three answers? $\endgroup$ Commented Feb 18, 2017 at 22:41

3 Answers 3

5
$\begingroup$

The key to sharing animations between objects is actions. An action is a sequence of animation keyframes that is linked to an object. The Action Editor is a sub-editor of the dopesheet.

When you have two or more objects that you want to share an action, select the new object then select the action in the action editor.

enter image description here

When you play the animation you will find that the two objects will now move in unison. There are two ways to adjust this, one is to make the animation unique to the object by clicking the number next to the Action Name. This duplicates the action, similar to duplicating a material etc. making it unique to the object allowing you to adjust the frames that the action is performed on.

Another option is to use the NLA Editor to adjust timing of the action.

enter image description here

Here you can see that metarig is playing action LiftLeg from frame 1, metarig.001 also has the LiftLeg action associated with it at frame 1. By clicking the down arrow icon (the arrow will be in 2.71, in earlier versions it looks like a snowflake) in line with metarig.001's LiftLeg action it will turn into an NLA track as seen with metarig. Now you will be able to adjust the action timing.

You can easily drag the action in the timeline to alter the start frame, but if you open the properties sidebar (press N) you also get access to more options like scale, repeat count and blend mode. Scaling allows a character to perform the action quicker or slower than other characters. You can have several actions for an object in the NLA at the same time and choose how they blend together, so you can have you character walking and then have a wave action override the arms at a given time.

enter image description here

Here the metarig repeats the walk cycle 5 times and just before the third time he starts waving.

If your using the game engine then you can use an Action actuator to play a specific action when you want it.

$\endgroup$
0
$\begingroup$

An armature is a Blender object, so you should be able to create a (set of) standard armatures, and have your creature creators append the appropriate armature, and animate it.

However, I've not tried to link or append animations, and consulting the Blender manual, it doesn't appear to me that the animation itself can be linked or appended.

$\endgroup$
1
  • $\begingroup$ I could be wrong, (I've never tried this myself) but objects usually bring all their datablocks with them when appending. So I think if you append the armature, the actions the armature uses should be appended too. $\endgroup$
    – gandalf3
    Commented May 20, 2014 at 6:21
0
$\begingroup$

I solved a similar task by creating a pose library with all required poses (same rig in my case a MHX rig) and a control file which contains the information which character and group of bones should get a pose assigned on a specific keyframe.

The keyframes are added to an action. This way each character has its own animation which can be tweaked.

The control file looks like:

0 SET:A=r6839a_proxy
0 SET:B=r6839b_proxy
1 A:All=Stance
1 B:All=Stance
10 B:Arm.L=Punch,Arm.R=Block
10 A:Arm.L=Hook

The first number is the keyframe in line #0 the rig proxy is assigned to a variable A/B to quickly change the character. Line #1 selects all bones and assigns a stance as starting position from a poselib that contains a pose called stance,

Line #10 Selects the left arm of the character B and assigns a Punch from the poselib.

Note: that I used forward kinematics for the arm and inverse kinematics for the legs.

The script that reads the control file:

import bpy
obj_map = {}

target_map = { "Root" : 0, "Spine" : 1, "ArmFK.L" : 3, "LegIK.L" : 4, "Fingers.L" : 6, 
                "Links.L" : 7, "ArmFK.R" : 19, "LegIK.R" : 20, "Fingers.R" :22, "Links.R" : 23 } 

macros = { "Hand.L": ["Fingers.L", "Links.L"],
           "Hand.R": [ "Fingers.R", "Links.R" ],
           "All":  ["Spine","ArmFK.L","ArmFK.R","LegIK.L","LegIK.R","Links.R","Fingers.R","Links.L","Fingers.L"],
           "Stance": ["Spine","Root","LegIK.L","LegIK.R"],
           "Arm.L": ["ArmFK.L","Links.L","Fingers.L"],
           "Arm.R": ["ArmFK.R","Links.R","Fingers.R"] }

def get_pose_index(obj, pose_name ):
    idx = 0
    for pm in obj.pose_library.pose_markers:
        if pose_name == pm.name:
            return idx
        idx += 1
    return None

def build_layers(targets):
    layers = [False]*32
    print( targets )
    for t in targets:
        if t in target_map:
            layers[target_map[ t ] ] = True
    return tuple( layers )

def apply( obj, targets, pose_name):
    idx = get_pose_index( obj, pose_name )
    if idx is None:
        print("pose %s not found." % pose_name )
        return
    sel_layers = build_layers( targets )
    bpy.ops.pose.armature_layers(layers=sel_layers)
    bpy.ops.poselib.apply_pose(pose_index=idx)    
    bpy.ops.pose.select_all(action='SELECT')   
    #if "Root" in targets:
    bpy.ops.anim.keyframe_insert(type='BUILTIN_KSI_LocRot')
    #else:
    #bpy.ops.anim.keyframe_insert(type='Rotation')


action="poon"
text=action + ".txt"


txt = bpy.data.texts[ text ].as_string()
for line in txt.splitlines():
    if line.find(" ") != -1 and line.find("#") == -1:
        sframe,rig_and_poses= line.split(" ")
        rest=rig_and_poses.split(":")
        print("frame :%s" % sframe )
        obj_name=rest[0]
        poses=rest[1]
        pose_list=poses.split(",")
        if obj_name.upper() == "SET":
            var,val = pose_list[0].split('=')
            obj_map[var]=val
            print( obj_map )
            continue

        bpy.context.scene.frame_set( int( sframe ))
        for assignment in pose_list:
            bone_group_name,pose_name=assignment.split("=")
            if bone_group_name in macros:
                targets = macros[ bone_group_name ]  
            else:
                 targets = [ bone_group_name ]
            obj = bpy.data.objects.get( obj_map[ obj_name])
            if obj == None:
                print("obj name=" + obj_name + " not found.")
                break
            bpy.context.scene.objects.active = obj
            obj.select = True  
            #print( obj.animation_data.action  )
            #if obj.animation_data.action == None:
            #    bpy.ops.action.new()
            #print( obj.animation_data.action  )
            #obj.animation_data.action.name = action + obj_name

            bpy.ops.object.mode_set(mode = 'POSE')  
            print("assign obj:%s bone_group:%s, pose:%s" % (obj, bone_group_name, pose_name))
            apply(  obj, targets, pose_name)

Some details: target_map is a dictionary which maps names used in the control script to rig-layer numbers (MHX)

macros is a collection for rig-layer adressed by single name e.g. 'All' for all rig-layers and Stance covers the root bone and both legs, thats to keep the control file short.

Around line 50:

action="poon"
text=action + ".txt"

Is the name of the control file it is directly used from the internal text editor. Related:

Can an action be mirrored or reused?

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .