Ragdoll bodies using armatures

I am probably not the first one to post something about this. I just want to know how to get ragdoll bodies using armatures and boxes, like in GTA IV and Saints row 2.

I have tried a few peoples tutorials but I cant get any of them working

thx in advance

You can link your boxes that make up your ragdoll with Rigid body constraints. I only use the 6DOF constraint (rotation limits are set in radians), but starting out with ball joints might be simpler

If you want the armature bones to follow objects (your ragdoll) in Blender 2.49b you have to use a script, which I put in the resource forum, and it is not 100% user friendly…

Blender 2.5 apparently has a function to link bones to objects, but I have not looked into it yet.

Animating ragdolls can be a challenge on it’s own and requires some programming skills, you can find the setup I used somewhere in the link I provided

Thx wraaah I can now get the armature and mesh following the cubes but the mesh deforms when the cubes move or rotate. Do you have an idea what the problem might be?

There are some annoying limits to the bone orientation in my script, which I tried to explain somewhere in the link I provided. The bones should all point in the same direction with the axes the same as the armature object. Bone starting points are at the centre of the objects. When everything is set up properly it works.

The problem is that I can not retrieve the starting orientation of bones at runtime so I use the armature orientation for all bones.

Thx wraaah I got it working but the axis were all correct the only problem was that the armature.init module i had to connect with an always sensor, I gave the sensor TRUE Level triggering, were I just saw only the update module must hav one. A stupid and small mistake but it made the difference.

Thx again now i can finally use ragdoll bodies!!!

So i tried the whole setup on a plain cube, but now that I try applying it to a character it just doesnt work. I attached the blend file. If anybody can please tell me what i’m doing wrong.


ragdoll_character.blend (138 KB)

The ears did not have objects to follow;
-either delete the ear bones
-add ragdoll ears
-add a try: function in the script so not every bone has to be controlled by an object

import GameLogic
from Blender import Mathutils
from Blender.Mathutils import *
#About the setup using the script:
# -I have tried to comment as much as possible to the script so do not get intimidated by the large amount of text :)
# -Give all the bones in the armature a name of an object (ragdoll) in the scene, these will controll the bones.
# -Put the bone head position at the same point as the origin of the controlling object.
# -All bones in the armature must be orientated (with their axes) in the same direction as the armature itself.
#  If the armature does not have a base orientation then this is easily accomplished by putting the bone tail somewhere
#  in the +Y direction of the head position. [ I found no access to the starting position/orientation of the individual
#  bones and the bone axes are used to set its local position. Without this data, the orientation must be predetermined
#  and I chose the armature axes.]
# -All (ragdoll) controlling objects must have the same starting rotation/orientation as the armature
#  [ I tried to remove this limitation, but I did not get it right. I do think that correcting for a different
#  starting orientation should be possible.]
# -Parent the character mesh to the armature as an armature, choose the group type based on your rigging choises. Of course
#  envelopes will not work because of the akward orientation requirements of the bones. But another armature could be used
#  to make the vertex groups seperatly...
# -The orientation of the armature is no longer limited, note that all the controlling objects still need to have the same rotation.
#  Therefore it is easiest to first create a working model and than move and rotate all the involved objects to the right spot in the game.
# -I use an ID property to quickly apply my scripts to multiple copied characters, Blender automaticcaly adds .001, .002 and so fort to
#  the copies so the ID is then "" for the original, ".001" for the first copy and so on...
# -The Target property contains the object that will controll the armature position, if the armatures origin is to far away from the camera
#  it will not be rendered.
# -An action actuator named "armature" must be applied to the armature, combined with an always sensor and 2 modules (Armature.update [run continuous]
#  & Armature.init [run once, high priority]).
# -I hope this list covers most details (I have sometimes spend days on very silly issues before I got some thing to work)
#Update the bone positions
def update(cont):
 arm = cont.owner
 ID = arm["ID"]
 #I use IDs because I want to apply the script to multiple copies, now I can copy + paste and only have to update the ID from .001 to .002 or something,
 #Keeping the ID blanc ("") will effectively ignore it
 scene = GameLogic.getCurrentScene()
 act = cont.actuators["armature"]
 targ = scene.objects[ "".join([ arm["Target"], ID]) ]
 #Set main position (The main armature/object must move along because else the object is no longer rendered when its original position falls off the camera)
 arm.worldPosition = targ.worldPosition
 arm_pos =  Vector( arm.worldPosition )
 M0_arm = GameLogic.globalDict[ "".join([ "Arm_Start_Orient", ID]) ]
 #For all bones in the list
 for chan in act.channelNames:
   ob = scene.objects[ "".join(["OB", chan, ID]) ] # Bones need to have the same name as their target objects
   loc,size,quat = act.getChannel(chan)
   #Update relative position
   ob_pos = Vector( ob.worldPosition )
   start_offset = GameLogic.globalDict[ "".join([chan, "_offset", ID]) ]
   pos = ob_pos - start_offset - arm_pos
   loc = M0_arm * pos   #Multiply by armature orientation because bone position is local/relative to armature
   #Update rotation
   M = Matrix( ob.worldOrientation[0], ob.worldOrientation[1], ob.worldOrientation[2] )
   quat = ( M0_arm * M ).toQuat()            #Change in rotation of the object
   quat[0] = -quat[0]   #Some weird angle inversion, it works but I don't know why it is nescessary
   #Update bone parameters
   act.setChannel(chan, loc, size, quat)
 #Apply settings
#Initialize stores starting offsets in global parameters 
def init(cont):
 arm = cont.owner
 ID = arm["ID"]
 scene = GameLogic.getCurrentScene()
 act = cont.actuators["armature"]
 #Set main offset
 arm_pos = Vector( arm.worldPosition )
 #Set orientation offset
 M_arm = Matrix( arm.worldOrientation[0], arm.worldOrientation[1], arm.worldOrientation[2] )
 M_arm_inv = M_arm.copy()
 GameLogic.globalDict[ "".join([ "Arm_Start_Orient", ID]) ] = M_arm_inv
 for chan in act.channelNames:
   ob = scene.objects[ "".join(["OB", chan, ID]) ]
   #Set position offset between bone and target object
   ob_pos = Vector( ob.worldPosition )
   GameLogic.globalDict[ "".join([chan, "_offset", ID]) ] = ob_pos - arm_pos

I also noticed that you placed the centre of the bones over the objects, this gives small errors. The bone centre is actually the starting point of the bone, not the middle. What I did to create my armatures was first to select the controlling object, then move the cursor to the object position (shift+s), then add a bone in the armature. If you have the proper viewport the bones are automatically orientated OK.

Ragdolls rule!!!:D:D:D

Hey Wraaah,

great setup! I was working on something similar, but your solution works even better than what I had until now. So I just dropped my stuff and use yours now, and it’s really good.
Here is a sample with your script and a live motion capture system:

I have to admit, that I had some problems setting up the bones and “dummy”(ragdoll-) objects. I will have to try that again on the whole body model.
But anyways: great work, and thank you for sharing :slight_smile:

edit: I just thought, that the motion capture system would be cool together with your fencing simulator :wink: I just have not enough time to try out :-/

thx man. its working now but i still have to give it some limits though.