Weapon-Based Animations [Solved]
by Jesse Allen · in Torque 3D Professional · 12/01/2014 (3:09 pm) · 14 replies
Hi all, I have an inquiry about changing Player animations depending on the weapon equipped.
I have a model that I set up with multiple LOD's and imported into Torque in a single .DAE file. The .DAE includes the animations for the model in a single track format. I separated the animations by frame in the Shape Editor. Check.
I understand the basic naming conventions used when setting up a character's animations, for example:
'root' will play when the Player is idle. 'Crouch_root' will play when the Player crouches. 'jump' will play when the Player jumps.
What I don't understand is how I setup weapon-specific animations. For example:
I'd like 'staff_root' to play when the Player is idle while holding a staff(mounted to slot 0). I'd like 'staff_crouch_root' to play when the Player crouches while holding a staff. I'd like 'staff_jump' to play when the Player jumps while holding a staff.
I can see in the example soldier.cs files that there are separate animations for Pistol, Lurker, etc. so obviously it is possible. I'm just not sure what I need to change or setup so that I can have Torque recognize my new weapons as equipped to trigger the weapon-specific animation 'states'.
Thanks in advance for any help :)
I have a model that I set up with multiple LOD's and imported into Torque in a single .DAE file. The .DAE includes the animations for the model in a single track format. I separated the animations by frame in the Shape Editor. Check.
I understand the basic naming conventions used when setting up a character's animations, for example:
What I don't understand is how I setup weapon-specific animations. For example:
I can see in the example soldier.cs files that there are separate animations for Pistol, Lurker, etc. so obviously it is possible. I'm just not sure what I need to change or setup so that I can have Torque recognize my new weapons as equipped to trigger the weapon-specific animation 'states'.
Thanks in advance for any help :)
About the author
Skilled Artist and Musician. Intermediate Torque Developer.
#2
12/01/2014 (3:49 pm)
github.com/GarageGames/Torque3D/blob/development/Templates/Full/game/art/datablo...
#3
I noticed that all of the default soldier animations (in the Anim folder) are split up into separate .dae files for each animation. Upon closer inspection of the accompanying .cs files with each animation, I can see that each animation shows a starting and ending frame, as if each one was at one time separated from a single track. The reason I think that this separation is important is because of the naming of the actual animation files, for example:
PlayerAnim_Lurker_Root.dae is the root animation while using the Lurker. PlayerAnim_Lurker_Death1.dae is one of the death animations while Lurker is equipped.
To recap: I do have the imageAnimPrefix = "Staff" set in the weapon datablock. I also have the animation like so in the Player's .cs file:
%this.addSequence("ambient", "Staff_Root", "4", "77", "1", "0");
What this is doing is splitting up the 'ambient' animation by frame #'s. The animations all play fine in the Shape Editor, and if I were to rename the above to just 'Root' instead of 'Staff_Root' it would default to it just fine. It just appears that perhaps single track animations split up like this don't work correctly with the ImageStateAnimation system? What's happening is the Player is defaulting to play 'ambient' when the mission starts up and he has the Staff equipped(ambient is all of the animations in a single track). I guess I could save out the animation in question to a separate file named with the same naming conventions used by 'PlayerAnim_Lurker_Root' just to test it out. Really seems like the single track animations should work though :/ I'll put in a little more investigation and hopefully get this pegged out soonish.
12/01/2014 (4:15 pm)
Hi Az, thanks for the input. I actually just stumbled on a little information about the weapon datablock's 'imageAnimPrefix' in an old doc but for some reason I'm still not having any luck. Honestly I believe it's due to me using a single track divided by frames for the animations. I noticed that all of the default soldier animations (in the Anim folder) are split up into separate .dae files for each animation. Upon closer inspection of the accompanying .cs files with each animation, I can see that each animation shows a starting and ending frame, as if each one was at one time separated from a single track. The reason I think that this separation is important is because of the naming of the actual animation files, for example:
To recap: I do have the imageAnimPrefix = "Staff" set in the weapon datablock. I also have the animation like so in the Player's .cs file:
%this.addSequence("ambient", "Staff_Root", "4", "77", "1", "0");
What this is doing is splitting up the 'ambient' animation by frame #'s. The animations all play fine in the Shape Editor, and if I were to rename the above to just 'Root' instead of 'Staff_Root' it would default to it just fine. It just appears that perhaps single track animations split up like this don't work correctly with the ImageStateAnimation system? What's happening is the Player is defaulting to play 'ambient' when the mission starts up and he has the Staff equipped(ambient is all of the animations in a single track). I guess I could save out the animation in question to a separate file named with the same naming conventions used by 'PlayerAnim_Lurker_Root' just to test it out. Really seems like the single track animations should work though :/ I'll put in a little more investigation and hopefully get this pegged out soonish.
#4
stateSequence[4] = "aim";
stateShapeSequence[4] = "aim";
pairing for instance. The latter triggers a specific animation on a player, so could use that if nothing else works, I suppose... Still, if that does turn out to be a segmentation flaw, would definitely bug-report that one via issues so it doesn't get buried.
12/01/2014 (4:33 pm)
Looks right, and have used similar setups in the past, though with the olderstateSequence[4] = "aim";
stateShapeSequence[4] = "aim";
pairing for instance. The latter triggers a specific animation on a player, so could use that if nothing else works, I suppose... Still, if that does turn out to be a segmentation flaw, would definitely bug-report that one via issues so it doesn't get buried.
#5
I've got the imageAnimPrefix in the weapon datablock:
I've got the actual prefix attached to the animation name:
The only difference I've found between what I've got and what the default Soldier is using is that the actual names of the .dae files in the soldier 'Anims' folder are using a naming convention like:
'PlayerAnim'_'Weapon'_'Name'
The source animation file I have contains over 6,000 animation frames and tbh it's too much work for me to go in and delete all those keyframes in each animation for separate export. There must be one other piece missing to this puzzle. The animations all play fine if they are simply named 'Root', 'Crouch_Root', and so on. It's only the ImageState animations that don't work.
12/01/2014 (6:32 pm)
Hmm, I'm not sure if it's a bug or I'm just not using the ImageAnimation system correctly. Following all available links, posts, and documentation this just won't work with different weapons as it should. I've got the imageAnimPrefix in the weapon datablock:
imageAnimPrefix = "Staff";
I've got the actual prefix attached to the animation name:
%this.addSequence("ambient", "Staff_Root", "4", "77", "1", "0");The only difference I've found between what I've got and what the default Soldier is using is that the actual names of the .dae files in the soldier 'Anims' folder are using a naming convention like:
'PlayerAnim'_'Weapon'_'Name'
The source animation file I have contains over 6,000 animation frames and tbh it's too much work for me to go in and delete all those keyframes in each animation for separate export. There must be one other piece missing to this puzzle. The animations all play fine if they are simply named 'Root', 'Crouch_Root', and so on. It's only the ImageState animations that don't work.
#6
Image state animation seems broken, or a very important piece of information regarding its proper usage is missing.
EDIT: ugh, just found another potentially ridiculous T3D problem...When you first import a model in .dae format you get a .cs file like so:
Well, what happens when you are done with the .dae file and you only want to use the generated cached .dts? For a release game, you'd not want to ship the source art. I just found that if you recreate the above script to be:
...shapes will load fine but any additional scripts like:
...will cease to function. In other words, if you add sequences, nodes, or whatever in the shape editor all those scripts are broken when you try to recreate the shape for release. If you look at the example Soldier scripts, you'll find that all of the scripts reference the DAE files. Ouch, that's a pretty big issue...
You can test this by changing the references to "art/shapes/actors/Soldier/soldier_rigged.DAE" to "art/shapes/actors/Soldier/soldier_rigged.cached.dts". If you do this and load up a mission, the default Soldier animations aren't loaded.
12/01/2014 (7:21 pm)
I just finally ended up testing this with another model I had that did have separate animations. I even renamed the animation file to follow the Soldier's weapon animation naming conventions. Image state animation seems broken, or a very important piece of information regarding its proper usage is missing.
- Regularly named animations work fine.
- Animations that should trigger based on what weapon is mounted don't work as they should.
EDIT: ugh, just found another potentially ridiculous T3D problem...When you first import a model in .dae format you get a .cs file like so:
singleton TSShapeConstructor(TestDae)
{
baseShape = "./Test.dae";
lodType = "TrailingNumber";
unit = "0.01";
ignoreNodeScale = "1";
loadLights = "0";
singleDetailSize = "0";
};Well, what happens when you are done with the .dae file and you only want to use the generated cached .dts? For a release game, you'd not want to ship the source art. I just found that if you recreate the above script to be:
singleton TSShapeConstructor(TestDts)
{
baseShape = "./Test.cached.dts";
lodType = "TrailingNumber";
unit = "0.01";
ignoreNodeScale = "1";
loadLights = "0";
singleDetailSize = "0";
};...shapes will load fine but any additional scripts like:
function TestDts::onLoad(%this)
{
%this.addNode("mount0", "Bip01_R_Hand", "0.651811 -0.0579402 1.09111 0.989302 0.131783 -0.0625659 0.0411092", "1");
}...will cease to function. In other words, if you add sequences, nodes, or whatever in the shape editor all those scripts are broken when you try to recreate the shape for release. If you look at the example Soldier scripts, you'll find that all of the scripts reference the DAE files. Ouch, that's a pretty big issue...
You can test this by changing the references to "art/shapes/actors/Soldier/soldier_rigged.DAE" to "art/shapes/actors/Soldier/soldier_rigged.cached.dts". If you do this and load up a mission, the default Soldier animations aren't loaded.
#7
Anyone know how to set up image mounted specific animations?
Also is it really true that ultimately cached.dts models don't hold the attached script info? I was really hoping I was just overlooking something, but I've been able to replicate that issue with several models now :/ When even the stock Soldier model is shipped with Torque in DAE format (with the scripts setup for DAE and not dts) I have to question if dts is even valid for animated characters in a released game.
12/02/2014 (9:12 am)
Bump.Anyone know how to set up image mounted specific animations?
Also is it really true that ultimately cached.dts models don't hold the attached script info? I was really hoping I was just overlooking something, but I've been able to replicate that issue with several models now :/ When even the stock Soldier model is shipped with Torque in DAE format (with the scripts setup for DAE and not dts) I have to question if dts is even valid for animated characters in a released game.
#8
In each weapon's folder you'll find a folder named 'PlayerAnims'. This folder will hold the scripts and .dae files for the weapon-specific animations. If you crack open those scripts you'll find that each animation is originally being named as the 'base' animation names. For example:
In art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Root.cs:
So you can see that what's happening here is the script is actually naming the animation the default 'Root' here. Meanwhile, back in the actual Player's script that same animation can be renamed to 'Pistol_Root'. BOOM! Works like a charm! Also if the animations are in a separate file, it is possible to just name the weapon specific animations with the prefix to begin with and it works, even with multiple animations in a single track :)
*Now, just need to find out what's the deal with .dts files losing hold of the scripts...but if I can't peg that out I'll create another thread about that.
12/03/2014 (1:23 am)
Alright, nailed it. The main cause of the problem was due to the imported .DAE holding the mesh data and the animations in a single file. Now, that's not to say that this doesn't work. It just doesn't work for Image State Animations. In other words, if you wanted to import the model, complete with LOD's and animations, nothing's wrong with that. Just don't expect that jumble of data to work as expected with the weapon image states. Here's why:In each weapon's folder you'll find a folder named 'PlayerAnims'. This folder will hold the scripts and .dae files for the weapon-specific animations. If you crack open those scripts you'll find that each animation is originally being named as the 'base' animation names. For example:
In art/shapes/weapons/Ryder/PlayerAnims/PlayerAnim_Pistol_Root.cs:
function PlayerAnim_Pistol_RootDAE::onLoad(%this)
{
%this.setSequenceCyclic("ambient", "true");
%this.addSequence("ambient", "Root", "50", "110");
}So you can see that what's happening here is the script is actually naming the animation the default 'Root' here. Meanwhile, back in the actual Player's script that same animation can be renamed to 'Pistol_Root'. BOOM! Works like a charm! Also if the animations are in a separate file, it is possible to just name the weapon specific animations with the prefix to begin with and it works, even with multiple animations in a single track :)
*Now, just need to find out what's the deal with .dts files losing hold of the scripts...but if I can't peg that out I'll create another thread about that.
#9
The reason it worked fine on the root animation is because it was the first one I added and the model had no other choice but to play the one animation available. Once I added another animation, once again, it didn't work. I added a 'Side' movement animation, and once again it will play and operate perfectly if I just name the animation "Side". But if I try to make it work as an weapon specific animaion by naming it to "Staff_Side" it won't play.
I've got the imageAnimPrefix in the weapon datablock:
I've got the actual prefix attached to the animation name:
I've got the animations separated into separate .dae files, each with their own scripts (exactly word for word copied from the Soldier weapon scripts). Example:
In art/shapes/weapons/Staff/PlayerAnims/PlayerAnim_Staff_Side.cs:
Finally, in the actual Player.cs I have the animations being renamed with the weapon prefix. Example:
In art/shapes/actors/TestChar/TestChar.cs:
I have everything line for line, file for file, down to the naming conventions and folder structure identical to what's provided with the soldier. Does anyone know what is wrong with Image State Animations?
*Also note that all of the animations will play fine if they are named to the default names (Root, Side, etc.). Image mounted specific animation is broken.
12/03/2014 (11:54 am)
Spoke too soon.The reason it worked fine on the root animation is because it was the first one I added and the model had no other choice but to play the one animation available. Once I added another animation, once again, it didn't work. I added a 'Side' movement animation, and once again it will play and operate perfectly if I just name the animation "Side". But if I try to make it work as an weapon specific animaion by naming it to "Staff_Side" it won't play.
imageAnimPrefix = "Staff";
%this.addSequence("ambient", "Staff_Side", "75", "113", "1", "0");In art/shapes/weapons/Staff/PlayerAnims/PlayerAnim_Staff_Side.cs:
singleton TSShapeConstructor(PlayerAnim_Staff_SideDAE)
{
baseShape = "./PlayerAnim_Staff_Side.dae";
loadLights = "0";
};
function PlayerAnim_Staff_SideDAE::onLoad(%this)
{
%this.setSequenceCyclic("ambient", "1");
%this.addSequence("ambient", "Side", "75", "113");
}In art/shapes/actors/TestChar/TestChar.cs:
function TestCharDae::onLoad(%this)
{
%this.addNode("mount0", "Bip01_R_Hand", "0.651811 -0.0579402 1.09111 0.989302 0.131783 -0.0625659 0.0411092", "1");
%this.addSequence("art/shapes/weapons/Staff/PlayerAnims/PlayerAnim_Staff_Root.dae Root", "Staff_Root", "0", "-1", "1", "0");
%this.addSequence("art/shapes/weapons/Staff/PlayerAnims/PlayerAnim_Staff_Side.dae Side", "Staff_Side", "0", "-1", "1", "0");
}I have everything line for line, file for file, down to the naming conventions and folder structure identical to what's provided with the soldier. Does anyone know what is wrong with Image State Animations?
*Also note that all of the animations will play fine if they are named to the default names (Root, Side, etc.). Image mounted specific animation is broken.
#10
12/05/2014 (3:02 am)
That seems kind of crazy. Thanks for the research here - sometime we should investigate and see what the problem with having animations all in the one file is. I think that'd count as a bug if it's true.
#11
Also, I believe I did finally figure out the problem with the .dts files. I think it comes down to a very specific naming convention with these files as well. There is an underscore that has to be used when naming the cached dts files. This seems to work:
12/10/2014 (9:05 pm)
@Danny: Hey Danny, don't get too worried about it just yet. I haven't dug 'deep' into the source code or anything yet to really peg out the issue. The problem is, though, I'm not able to get the animation 'state' to update when equipping different weapons - with single-track or multi-track animation files. This being the case, I'm more inclined to think it's just some small important detail being overlooked setting it all up. Animations all work fine in single or multi track setups, so long as the regular naming conventions are used('root', 'run', 'side', etc.). Problems only arise trying to add prefixes to the animation names. /shrugAlso, I believe I did finally figure out the problem with the .dts files. I think it comes down to a very specific naming convention with these files as well. There is an underscore that has to be used when naming the cached dts files. This seems to work:
singleton TSShapeConstructor(Test_cachedDts)
{
baseShape = "./Test.cached.dts";
lodType = "TrailingNumber";
unit = "0.01";
ignoreNodeScale = "1";
loadLights = "0";
singleDetailSize = "0";
};
function Test_cachedDts::onLoad(%this)
{
%this.addNode("mount0", "Bip01_R_Hand", "0.651811 -0.0579402 1.09111 0.989302 0.131783 -0.0625659 0.0411092", "1");
}
#12
1- Be sure that you first have an 'ambient' animation added to the Player model's onLoad() function that holds all the animations in a single track. If the model is a cached .dts file, be sure to add the '_cachedDts' extension to the name of the shape:
2- The above should be in a .cached.cs file(the extension is not just .cs) for cached.dts shapes.
3- Go ahead and split up the 'ambient' animation into other base animations for the Player before worrying about any weapon-based animations. These animations should be the standard animations for the player with no weapons( or default animations). For example, go ahead and assign 'Root', 'Run', 'Side', 'Jump' animations from the single track:
4- Now that some basic animations are in place for the Player shape, we can extend the list of Player animations to include weapon-based animations. So, for example, when the Player equips a Staff the animations that have been prefixed with 'Staff_' will play instead of the base(default) animations we just added. In this step, it is important that you reference the animation being replaced in the script:
5- With the new 'Staff_Root' animation in place, be sure to set the imageAnimPrefix in the Staff's datablock:
With the above in place, when the Player switches to the Staff weapon he will play the 'Staff_Root' animation. All of the default animations can be replaced as above so that the Player has a full range of animations for each weapon it equips. Here's an example with 4 default animations and 4 weapon-based animations:
Anyways, I mainly wanted to put this out there since I hadn't found much detailed information about the process. Also for my own future reference :)
Hope this helps someone out there, keep on Torquing!
01/01/2015 (1:27 pm)
I just stumbled on this post again, and had forgotten about this. I just wanted to post in that I did finally solve this, and confirm that there is no bug with singleTrack animations. Just in case anyone runs into problems, here is the why and the how of what went wrong for me(basically a small walkthrough). To get this all working so that the player will change animations based on the equipped weapon, there are some prerequisites that must be met:1- Be sure that you first have an 'ambient' animation added to the Player model's onLoad() function that holds all the animations in a single track. If the model is a cached .dts file, be sure to add the '_cachedDts' extension to the name of the shape:
singleton TSShapeConstructor(TestShape_cachedDts)
{
...
}
function TestShape_cachedDts::onLoad(%this)
{
%this.addSequence("./Anims/TestShapeAnimations.cached.dts", "ambient", "0", "-1", "1", "0");
...
}2- The above should be in a .cached.cs file(the extension is not just .cs) for cached.dts shapes.
3- Go ahead and split up the 'ambient' animation into other base animations for the Player before worrying about any weapon-based animations. These animations should be the standard animations for the player with no weapons( or default animations). For example, go ahead and assign 'Root', 'Run', 'Side', 'Jump' animations from the single track:
function TestShape_cachedDts::onLoad(%this)
{
...
%this.addSequence("ambient", "Root", "1", "50", "1", "0");
%this.addSequence("ambient", "Run", "51", "70", "1", "0");
%this.addSequence("ambient", "Side", "71", "90", "1", "0");
%this.addSequence("ambient", "Jump", "91", "110", "1", "0");
...
}4- Now that some basic animations are in place for the Player shape, we can extend the list of Player animations to include weapon-based animations. So, for example, when the Player equips a Staff the animations that have been prefixed with 'Staff_' will play instead of the base(default) animations we just added. In this step, it is important that you reference the animation being replaced in the script:
function TestShape_cachedDts::onLoad(%this)
{
...
// Replace the 'ambient' track's 'Root' animation
// with 'Staff_Root'
%this.addSequence("ambient Root", "Staff_Root", "111", "160", "1", "0");
...
}5- With the new 'Staff_Root' animation in place, be sure to set the imageAnimPrefix in the Staff's datablock:
datablock ShapeBaseImageData(StaffImage)
{
...
shapeFile = "art/shapes/weapons/Staff/Staff.cached.dts";
imageAnimPrefix = "Staff";
...
}With the above in place, when the Player switches to the Staff weapon he will play the 'Staff_Root' animation. All of the default animations can be replaced as above so that the Player has a full range of animations for each weapon it equips. Here's an example with 4 default animations and 4 weapon-based animations:
function TestShape_cachedDts::onLoad(%this)
{
...
%this.addSequence("./Anims/TestShapeAnimations.cached.dts", "ambient", "0", "-1", "1", "0");
%this.addSequence("ambient", "Root", "1", "50", "1", "0");
%this.addSequence("ambient", "Run", "51", "70", "1", "0");
%this.addSequence("ambient", "Side", "71", "90", "1", "0");
%this.addSequence("ambient", "Jump", "91", "110", "1", "0");
%this.addSequence("ambient Root", "Staff_Root", "111", "160", "1", "0");
%this.addSequence("ambient Run", "Staff_Run", "161", "180", "1", "0");
%this.addSequence("ambient Side", "Staff_Side", "181", "200", "1", "0");
%this.addSequence("ambient Jump", "Staff_Jump", "201", "220", "1", "0");
...
}Anyways, I mainly wanted to put this out there since I hadn't found much detailed information about the process. Also for my own future reference :)
Hope this helps someone out there, keep on Torquing!
#13
01/01/2015 (4:12 pm)
Awesome! Thanks for that. I'll make this into a wiki page sometime, unless you want to do it yourself ;).
#14
01/02/2015 (8:49 am)
No problem, the more detailed guides available the better. Feel free to convert to wiki as I'm currently a bit busy :)
Torque Owner James Novosel
Default Studio Name
game\art\shapes\actors\Soldier\Anims
Then take a look at the .cs files in
game\art\shapes\weapons\Ryder\PlayerAnims or any weapon directory
I think that game\art\shapes\actors\Soldier\soldier_rigged.cs ties it all together. How the engine know to switch to what animation
There is a section on the player class in the Torque3d_ScriptManual.chm file:
Mounted Image Controlled 3rd Person Animation
A player's 3rd person action animation sequence selection may be modified based on what images are mounted on the player. When mounting a ShapeBaseImageData, the image's imageAnimPrefix field is used to control this. If this is left blank (the default) then nothing happens to the 3rd person player -- all of the sequences play as defined. If it is filled with some text (best to keep it to letters and numbers, with no spaces) then that text is added to the action animation sequence name and looked up on the player shape. For example:
A rifle ShapeBaseImageData is mounted to the player in slot 0. The rifle's datablock doesn't have an imageAnimPrefix defined, so the 3rd person player will use the standard action animation sequence names. i.e. "root", "run", "back", "crouch_root", etc.
Now a pistol ShapeBaseImageData is mounted to the player in slot 0. The pistol's datablock has imageAnimPrefix = "pistol". Now the "pistol_" (underscore is added by the system) prefix is added to each of the action animation sequence names when looking up what to play on the player's shape. So the Player class will look for "pistol_root", "pistol_run", "pistol_back", "pistol_crouch_root", etc. If any of these new prefixed names are not found on the player's shape, then we fall back to the standard action animation sequence names, such as "root", "run", etc.
Looks like there are .dae as well as .cs specific files covering animations for each weapon and the engine uses the weapon and pose and animation (root/run/crouch) to know which .dae to use.
Also struggling with this in an attempt to integrate Miaxmo Fuse characters.
Probably repeating what you already know, hope this helps