PDA

View Full Version : Tutorial Making a Skeletal Control to move an arm



Cozmicaztaway
06-24-2010, 11:26 AM
So this (http://udn.epicgames.com/Three/UsingSkeletalControllers.html) is pretty cool, for a number of reasons. It's also sort of hard to use and there's not a whole lot of tutorials for it that I know of (bet everyone's been writing these things while I've been of coding other stuff, but still). So ta-daa, tutorial time!

What we're going to do here is fairly simple: we're going to attach a Skeletal Control to the arm of a standard Unreal Tournament Mesh/AnimTree, and tie this to our code so we can move this arm freely in a 2-dimensional plane. Picture the arms of Sackboy in LittleBigPlanet if you will. This is simply how I've done things, and i'm sure with more modeling skills etc you could make lots of cool things, like a spiffy prehensile tail or a trunk of an elephant or what-not.

This tutorial uses a lot from the UT demo included in the UDK, so mostly it is simply overriding and stuff. It should be incredibly similar to use it if not inheriting from UT however.

Anyway, to the ARM-MOVEMENT-MAKING!

1. Open up the UDK editor. We need to create a Skeletal Control for us to use, so we need to fiddle with the editor a bit. Don't worry, we won't break anything (well, I won't, anyway).

2. Copy CH_AnimHuman_tree. So we don't screw up the original things, make a copy of the AnimTree we'll be modifying. You'll be working with the copy, so name it something useful, like "CH_AnimHuman_MyTree" or similar. Remember the name and remember the package (or just dig them up later).

3. Make a new Skeletal Control. Ok, so open up the AnimTree you just created if you haven't already. You should now see a big grey field filled with various Skeletal Controls, Animnodes and, most importantly a blue box name AnimTree containing the names of bones, such a b_LeftAnkle and b_LeftHand.
Right click in the grey field somewhere where it's not too cluttered, and select New Skeletal Control. For this tutorial, since we're moving an arm, SkelControlLimb might seem like the ideal candidate. However, this only controls 2 bones and an entire arm actually contains a whole lot of bones. So instead, we will create a SkelControl_CCD_IK, which is basically like a tentacle or long string of bones that bruteforces bone position to work. They power the tentacles of the Reavers in Gears of War. You should now have a SkelControl_CCD_IK lying around, in a greenw indow titled "SkelControl_CCD_IK: None". We need to name this, so simply scroll down the properties list (should be at the bottom of the screen) until you find Controller Name. name it something without spaces, you need this name for the code later on. I named mine RightArmIK, as we're controlling Inverse Kinematics in the arm/with the arm/whatever.

4. Connect the Skeletal Control to a bone on the AnimTree. This is where we connect the SkelControl to our skeleton. Simply drag from the "In" portion of the SkelControl node we created to the bone you want to control. This should be the outermost limb, or the bottom child, of the limb. Mine connected to b_RightWeapon so I have control over the outermost limb of the arm, with the weapon, hand and everything.

5. Set the properties of the SkelControl. This step is probably the hardest part of the entire tutorial, as you need to make sure all the AngleConstraints work properly and this is a rather enormous pain. You also need to check just how many bones you want in the chain, as this will affect a lot of things. There is a lot of trial and error in this stage, and i have not quite gotten the hang of it myself, so if someone gets a better value for this whole thing, feel free to let me know.
For our arm-purposes, we will set "Num Bones" in the CCD properties to 5. This goes from the weapon up to the shoulder blade, more or less, giving a fairly good control of the entire right arm.
AngleConstraints are how much each individual bone may move and, like I said, I am not entirely sure how this works with one bone in relation to another. Trial and error, people.
Mine are set to:
[0]= 0.000
[1]= 0.900
[2]= 0.200
[3]= 0.900
[4]= 0.100
Max Angle Steps= 2.100 (the sum of the steps)

Remember to set your Controller Strength appropriately. 0.0 is no control, 1.0 is full control, entirely overriding any animations.

Finally, set "Ignore at or above LOD" to a high number, like 1000, so you can see it even from a distance.

6. Save the Package We are more or less done with the editor now, so save the package. Now we're getting to the fun/comfortable part: Coding!

7. Set up the pawn class to handle your SkelControl. Open up the pawn class you are using (you can just extend UTPawn, or the UT2D pawn or something to keep matters simple if you want).
We need to add a new variable for our SkelControl, so simply add a new Skelcontrol variable named after the type and a useful name (I prefer the same as the one we used for the controller name in the anim tree)
For example:

var SkelControl_CCD_IK RightArmIK;

There, we now have a SkelControl that we can call from other classes (our PlayerController class, for instance). We do not have it initialized or have anything to initialize, however, so scroll down to the DefaultProperties. We need to change which AnimTreeTemplate our pawn uses, so it finds our shiny new SkelControl. If you're extending UTPawn, then this value is set in WPawnSkeletalMeshComponent, so override that one. To do this, just add this in your DefaultProperties:

Begin Object Name=WPawnSkeletalMeshComponent
AnimTreeTemplate=AnimTree 'CH_AnimHuman_MyTree.AT_CH_MyTree'
End Object
Where the AnimTree path should be the name of your package and AnimTree you created. If you can't remember it, just right-click it in the content broswer of the editor and choose "copy full name to clipboard" and paste.

8. Initialize the skeletal control. Ok, so now we have the controller and the AnimTree set up, but we don't have the Controller in the AnimTree actually hooked up to our variable. The best way to do this, if UTPawn does it the best, is to initialize these in PostInitAnimtree. So, simply overriding again, we do this:

simulated event PostInitAnimTree(SkeletalMeshComponent SkelComp)
{
super.PostInitAnimTree(SkelComp);
RightArmIK = SkelControl_CCD_IK( mesh.FindSkelControl('RightArmIK') );
}
This finds the controller, assigns it a pointer, and now we have our variable fixed. So now, to USE IT!

9. Modifying PlayerController. Since the pawn is controlled by playerController, we're going to modify PlayerController to give us total control of the arm. Once again, i inherited from Unreal tournament, so these steps might be different if done otherwise. This bit is going to be a lot of code, so apologies in advance. The basic thing being done is that in UpdateRotation we use the values of the mouse input or the right stick input on a gamepad to declare a vector position which our arm will then strive to reach.
So, basic code:


function UpdateRotation(float DeltaTime)
{
local vector ArmLocation;
local MyPawn Utp;
ArmLocation.Z += PlayerInput.aLookup*10+100; //giant multiplier so we extend the arm more.
ArmLocation.X += PlayerInput.aTurn*10;
Utp=MyPawn(Pawn); //this simply gets our pawn so we can then point to our SkelControl
Utp.RightArmIK.EffectorLocation=Pawn.Location + ArmLocation;
}

There, on that last line we set the EffectorLocation, meaning where the limb is trying to be, to the ArmLocation Vector, and the arm should move whenever you move the mouse. Now, if you're running this into UT2D like i did, you might notice that if your character is facing the opposite direction from where you are pointing your arm, it does this sort of weird hook thing when trying to aim backwards, as opposed to stretching out fully. This issort of LBP-ish, so we can keep it, but if you want to get rid of it, keep track of where the character is looking and where the arm is pointing (I stored the "I'm looking this way" direction into a float called LastX) and then set bStartFromTail to false if they're opposites. you might remember bStartFromTail from the properties in the editor, and you can set it in code as well. If true, this means we start from the opposite end of the chain and not the bone we started the chain in (so we would not start from the weapon but around the shoulder).
Here's the code I used to make this check:


if((LastX>0 && PlayerInput.aTurn <0) || (LastX<0 && PlayerInput.aTurn>0)) //if we're aiming backwards with the right hand, start from tail
Utp.RightArmIK.bStartFromTail=true;
else
Utp.RightArmIK.bStartFromTail=false;

This should go before you set the EffectorLocation, so it actually has any effect.

And that's it! I didn't realize I did so many steps to get this to work! Sorry about the lack of pictures, sorry about the mess and, in general, I'm just sorry I guess. This is my first tutorial and I think it is one people might find some use out of.
Thanks for reading, and hopefully this will keep you from pulling your hair like I did.

Video of this working hopefully forthcoming soon as well!

EDIT: oh yeah, durr, if there's any questions, just ask and i'll try and answer to the best of my capabilites.

UPDATE: So, finally got around to uploading the gameplay video of our project we did, which shows this off. Video can be viewed HERE (http://www.youtube.com/watch?v=9SRdSXAC0jQ)

toxicFork
06-24-2010, 11:35 AM
Awesome, I'll try it as soon as I get home.

danimal'
06-25-2010, 02:38 PM
Very cool, not the usual tutorial and very much appreciated!

AlbinoWarrior
06-29-2010, 12:27 AM
I like it, it will probably help me in the future...

Monophobe
07-27-2010, 09:58 PM
Nice tutorial. Would you mind looking at the issue I've got here please. Sounds like this is almost what I'm after but using a UDKSkelControl_LookAT - http://forums.epicgames.com/showthread.php?t=739294

Cozmicaztaway
08-11-2010, 09:35 AM
Nice tutorial. Would you mind looking at the issue I've got here please. Sounds like this is almost what I'm after but using a UDKSkelControl_LookAT - http://forums.epicgames.com/showthread.php?t=739294

Sorry I didn't help you out with that, looks like it sorted itself out however. Came down all feverish and stuff and didn't exactly feel like thinking :o

vichnaiev
08-19-2010, 02:24 PM
I had no luck following this tutorial. Could you help me find out what's wrong?

I followed it exactly, but on top of an already existing code base (UT2D heavily modified code), so there might be other code breaking it.

The only thing I did different from you was the bone, cause in UDK there is no b_RightWeapon, but there is b_IKGun which seems to be the same (I could be wrong).

I sent a debug message to console to make sure that it Location got set, here's the output when I move the mouse (and nothing happens to the pawn).

Edit: nevermind, the bone b_RightWeapon was there, I just had to add it to blue box. Now it works, it's just a matter of tuning it so it doesnt behave all crazy.

thelaw
10-22-2010, 11:32 AM
Thanks for the tutoria, was actually looking into controlling my pawns arms.

Wyldhunt
10-23-2010, 01:57 AM
How did this tutorial get missed on http://udkc.info?
It should be there. This is one of those things that can take a lot of work to figure out.

Blade[UG]
10-24-2010, 02:22 AM
Hmm. I'm poking around through some of this stuff, and I'm noticing that all of the subclasses of SkelControlBase define their own things, even though most of them share the exact same information. Is there a reason why this is, I wonder?

Blade[UG]
10-24-2010, 04:23 AM
Tip: If you want to see the effects of your IK in the editor, before you start putting the code down (especially useful if you find you need to use a different SkelControl, since they aren't compatible with each other codewise), if you select the SkelControl in the AnimTree editor, there should be a little diamond that you can move around in the Preview window, that will allow you to adjust the various Location attributes in the SkelControl (EffectorLocation in this example, BoneTranslation in another, etc). Then you can adjust the slider in the animtree to see how it will affect your bones.

Zeraphil
10-26-2010, 11:49 AM
This is fine if you want the arm to reset constantly to its standard position, but what if you want a 1:1 control of the arm via input?

Simply intialize ArmLocation and the Pawn as variables of your PlayerController, as such:


class MyPlayerController extends UTPlayerController;

var vector ArmLocation;
var MyPawn Utp;


and delete the local calls in UpdateRotation.

Sir. Polaris
10-28-2010, 09:21 AM
How did this tutorial get missed on http://udkc.info?
It should be there. This is one of those things that can take a lot of work to figure out.

If the original author is ok with it, I will put it on the website in quick time. It's a great tutorial, on a topic I been trying to figure out myself :)

Wyldhunt
10-29-2010, 12:45 AM
If the original author is ok with it, I will put it on the website in quick time. It's a great tutorial, on a topic I been trying to figure out myself :)

I PMed them, but they didn't respond. I'm not sure if they still frequent the boards.

Sir. Polaris
10-29-2010, 05:15 PM
Yea, I did as well a well a while back. It took a week or so for him to respond :D

Cozmicaztaway
11-11-2010, 06:35 AM
I don't frequent this place as much as I should, I guess. Between currently not developing in the UDK (withdrawal symptoms are terrible, btw) and having tons of stuff to do, they have sort of fallen by the wayside. i do try and check in every so often to at least check PMs though.

Sir. Polaris
11-11-2010, 07:53 AM
You cannot resist :D - Come backkk to usss.....

Whitenorthstar
11-15-2010, 12:44 AM
By the way, Pangareux is looking like a lot of fun! http://www.youtube.com/watch?v=9SRdSXAC0jQ

Of course, it's based on a bunch of 2d arcade games, but it's faster, with more movement, and potentially more action... Ur main character and his animation is bizarrely appealing, too. heck, I might buy it myself!

I know Urs is just a proof of concept, but this dissolve material effect from Piranhi would suit Ur game very well, to get rid of Ur dead robots:

http://udkbase.com/index.php?option=com_content&view=article&id=46:piranhi1&catid=36:elemental-type&Itemid=68

Also, how about a grapple hook, like Ropeman or Bionic Commando. Grapple hooks can be in 2d also, not only 3d like Just Cause 2. It's easy to implement, and would add another layer of variety, verticality, puzzle solving and physics to Ur gameplay... just my 10 cents worth :D

Cozmicaztaway
11-16-2010, 09:49 AM
By the way, Pangareux is looking like a lot of fun! http://www.youtube.com/watch?v=9SRdSXAC0jQ

Of course, it's based on a bunch of 2d arcade games, but it's faster, with more movement, and potentially more action... Ur main character and his animation is bizarrely appealing, too. heck, I might buy it myself!

I know Urs is just a proof of concept, but this dissolve material effect from Piranhi would suit Ur game very well, to get rid of Ur dead robots:

http://udkbase.com/index.php?option=com_content&view=article&id=46:piranhi1&catid=36:elemental-type&Itemid=68

Also, how about a grapple hook, like Ropeman or Bionic Commando. Grapple hooks can be in 2d also, not only 3d like Just Cause 2. It's easy to implement, and would add another layer of variety, verticality, puzzle solving and physics to Ur gameplay... just my 10 cents worth :D

Dude, you have NO IDEA how crazy this thing is getting! And thanks, but yeah, redoing it and making it awesome!

And Sir Polaris: Dude, I'm TRYING!

Sir. Polaris
11-16-2010, 10:53 AM
http://www.geekalerts.com/u/yoda-cookie.jpg
Do or do not, there is no try! :D

PS: Heres a cookie for the troubles :D

daimaku
12-21-2010, 10:58 AM
thanks for the tutorial Cozmicaztaway, very usefull thing ....

gord10
02-12-2012, 09:46 AM
That's a great tutorial!

Unfortunately, I couldn't manage moving my player pawn's hand in an acceptable way. I've tried many combination of different bone amounts, maximum angles and some other parameters, but I couldn't get a satisfying result.
http://www.image-share.com/upload/1281/253m.jpg (http://www.image-share.com/ijpg-1281-253.html)

I couldn't find a b_RightWeapon bone in my CH_AnimHuman_Tree, so I tried tieing the SkelControl_CCD_IK (labeled 'RightArmIK') with some other bones, but none of them worked like the way I wanted. All the difference between what I do and told in the tutorial is the bones connected to the RightArmIK. I would greatly appreciate that if someone would give me any idea about which bone should be attached to our RightArmIK in the new version of UDK and what their parameters are.

Thanks in advance,

Ahmet K. Keleş

aries420
02-21-2012, 05:16 PM
hmm how would you go about getting this to attach to a socket or even another skeletal mesh like a gun rather than fallow where i am aiming?

Harmageddon
02-28-2012, 09:48 AM
Perhaps this is a stupid question, but how can I define an arm move that is performed when the player clicks with the mouse? (for example for hitting something or somebody)

Zablar
07-06-2012, 12:48 PM
Possible to use this in a FPS game for e.g. pushing buttons?