T3D 1.2 (and earlier) - AIPlayers move without animating **Possible Fix included
by Guy Allard · in Torque 3D Professional · 07/11/2012 (6:33 am) · 23 replies
Build: T3D 1.2
Platform: vista
Target: game
Issues:
There are numerous posts on the forum where people describe AIPlayers moving without animating (gliding). This has been an issue with all versions of T3D, and has been logged as resolved, but I'm seeing it a lot more frequently in T3D 1.2.
The issue is random, sometimes they will play the correct movement animation, sometimes not.
I am experiencing this with an unmodified Player/AIPlayer so the issue is not related to any modifications to those classes.
Steps to repeat:
Launch the game, using the emptyRoom.mis
Spawn an AIPlayer.
Make it move somewhere.
If it animates correctly, delete it and repeat. Eventually one will fail to animate and slide along the ground.
Notes:
Looking into this, I have found that when the AIPlayer slides, it is due to pickActionAnimation returning PlayerData::RootAnim because the mContactTimer for the AIPlayer is >= sContactTickTime. This should not be true if the player is on the ground.
Digging further, the contactTimer is updated in updateMove() which is called from processTick.
Debugging shows that the sliding AIPlayers are not calling updateMove from processTick, and so are not correctly determining that they are on the ground.
Digging some more, the reason that updateMove is not being called, is that for the AIPlayers, delta.warpTicks is almost always non-zero. This is true even for AIPlayers which are stationary. in processTick, if delta.warpTicks > 0, some warping is performed instead of calling updateMove.
To confirm this yourself, add the following to Player::processTick, right after the Parent::processTick(move) and before the if(delta.warpTick..............
So it looks like something is screwed up down in the bowels of the player warping code when it's being used by an AIPlayer.
Also, I have noticed that with a correctly animating AIPlayer, if an impulse is applied, lifting him into the air at the same time as he's moving horizontally, he continues to play the movement animation while in the air. He shouldn't, as if he's in the air, pickActionAnimation should return RootAnim. This issue is again due to what I've discussed above.
It seems to be that the only reason that AIPlayers behave correctly most of the time is pure chance - at some point their warpTicks were 0 and updateMove got called while they were on a surface.
***Edit***
See post #17 for a workaround
Platform: vista
Target: game
Issues:
There are numerous posts on the forum where people describe AIPlayers moving without animating (gliding). This has been an issue with all versions of T3D, and has been logged as resolved, but I'm seeing it a lot more frequently in T3D 1.2.
The issue is random, sometimes they will play the correct movement animation, sometimes not.
I am experiencing this with an unmodified Player/AIPlayer so the issue is not related to any modifications to those classes.
Steps to repeat:
Launch the game, using the emptyRoom.mis
Spawn an AIPlayer.
Make it move somewhere.
If it animates correctly, delete it and repeat. Eventually one will fail to animate and slide along the ground.
Notes:
Looking into this, I have found that when the AIPlayer slides, it is due to pickActionAnimation returning PlayerData::RootAnim because the mContactTimer for the AIPlayer is >= sContactTickTime. This should not be true if the player is on the ground.
Digging further, the contactTimer is updated in updateMove() which is called from processTick.
Debugging shows that the sliding AIPlayers are not calling updateMove from processTick, and so are not correctly determining that they are on the ground.
Digging some more, the reason that updateMove is not being called, is that for the AIPlayers, delta.warpTicks is almost always non-zero. This is true even for AIPlayers which are stationary. in processTick, if delta.warpTicks > 0, some warping is performed instead of calling updateMove.
To confirm this yourself, add the following to Player::processTick, right after the Parent::processTick(move) and before the if(delta.warpTick..............
if(mIsAiControlled && !isServerObject())
Con::printf("warpTicks: %d", delta.warpTicks);Then run the game with an AIPlayer and look at the console. The AIPlayer is in a continual state of warp (cool).So it looks like something is screwed up down in the bowels of the player warping code when it's being used by an AIPlayer.
Also, I have noticed that with a correctly animating AIPlayer, if an impulse is applied, lifting him into the air at the same time as he's moving horizontally, he continues to play the movement animation while in the air. He shouldn't, as if he's in the air, pickActionAnimation should return RootAnim. This issue is again due to what I've discussed above.
It seems to be that the only reason that AIPlayers behave correctly most of the time is pure chance - at some point their warpTicks were 0 and updateMove got called while they were on a surface.
***Edit***
See post #17 for a workaround
About the author
Recent Threads
#22
The solution I posted works, but was just something I mashed up after pulling my hair out trying to cure the problem. I could not get it to work without some way for the server to tell the client ghost that a contact has occurred, because the current stock animation system needs this information to pick the correct animation.
11/28/2012 (8:42 am)
So do you know of another way to fix this?The solution I posted works, but was just something I mashed up after pulling my hair out trying to cure the problem. I could not get it to work without some way for the server to tell the client ghost that a contact has occurred, because the current stock animation system needs this information to pick the correct animation.
#23
The client ghost has velocity. That means you know if it is falling (velocity.z < tolerance1),jumping (velocity.z > tolerance2), walking (velocity.len() < tolerance3), running(velocity.len() >= tolerance3)...
Some animations need to be send as well (shoot, hit...). You send a state and a pose also.
I believe the gliding clients are due to picking the null animation and you're losing animation advancing. Having a logic based on a velocity will skip gliding because in the worst scenario you are losing updates,your ghost's velocity is zero and you set the root sequence.
The physics code has a logic of bouncing the collision box in a very tiny reflection forces to avoid collision locking. That means if you are moving on a ground and hit an edge, your timer should be positive when you are on the ground.And if you send the timer you would set multiple sequences in continuous updates resulting in some weird transitions.
11/29/2012 (4:23 am)
The solution to fix that was to split the logic of picking an animation.The client ghost has velocity. That means you know if it is falling (velocity.z < tolerance1),jumping (velocity.z > tolerance2), walking (velocity.len() < tolerance3), running(velocity.len() >= tolerance3)...
Some animations need to be send as well (shoot, hit...). You send a state and a pose also.
I believe the gliding clients are due to picking the null animation and you're losing animation advancing. Having a logic based on a velocity will skip gliding because in the worst scenario you are losing updates,your ghost's velocity is zero and you set the root sequence.
The physics code has a logic of bouncing the collision box in a very tiny reflection forces to avoid collision locking. That means if you are moving on a ground and hit an edge, your timer should be positive when you are on the ground.And if you send the timer you would set multiple sequences in continuous updates resulting in some weird transitions.
Torque Owner Ivan Mandzhukov
Liman3D
Picking an animation from a timer is a bad idea for a ghost.