Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

PuppetMaster - Advanced Character Physics Tool [RELEASED]

Discussion in 'Assets and Asset Store' started by Partel-Lang, Oct 1, 2015.

  1. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Hey,
    Not sure I understood right.. If your puppet rolls down a hill, it should do so while in an unpinned state so there should be no pinning forces to pull it back up. Once the ragdoll settles, the target root should be moved to the hips of the ragdoll and a get up animation played, that's how BehaviourPuppet does it.

    The whole point of PuppetMaster is to make a ragdoll follow an animation and it does so by employing the joints to simulate the muscles and pinning to take care of the rest. Humans don't have the technology yet to make physical rigs move around following a percise pattern of motion without falling over, if we did, we'd already see robots walking around everywhere. Pinning is an unnatural force applied to the puppet, but it's the only way to simulate that kind of behaviour I'm afraid.

    It will always lag behind a kinematic rig, it's inevitable, dynamic rigs need to be accelerated, kinematic rigs don't.
    That's why BehaviourPuppet has "Unmapped" and "Kinematic" modes, to maintain your animation quality until there is a collision that needs to be solved.

    About the problem of what happens if an external force moves the puppet away from the animated position. BehaviourPuppet handles that by checking the distance of the muscles from their targets.. If it is less than knockOutDistance, it will allow for the pinning to pull the muscles back, if it's more, it will cause the puppet to lose balance and enter the unpinned state in which all pinning is disabled until the ragdoll settles and a getting up procedure is initiated. Do you have a better idea on how to do that?

    Yes, that is why Unity doesn't have active ragdolls integrated yet.

    Cheers,
    Pärtel
     
  2. RakNet

    RakNet

    Joined:
    Oct 9, 2013
    Posts:
    313
    1. Apply gameplay transformation deltas to the root node of both the ragdoll and the animated character. Gameplay should read the character position from the position of the hips.. If the ragdoll hips transformation differs significantly from the animated character hips transformation for a given Update(), this must have been due to physics forces other than pinning. Therefore, every Update() match the animated character hips transformation to the ragdoll hips transformation.
    2. Per-Fixed update, determine which component of motion on the hips is due to pinning, and which is due to external physics. For the force that is due to external physics, apply the same positional and rotational velocity deltas to the rigid body used by the character controller.
    3. Do not use a dual-rig setup, or give the option to not use one. Treat the hips as the character's position.

    The problem with solution #1 is it adds even more complexity to the system. You have to write your transformation deltas to the root node, but read your current position from the ragdoll hips.
    #2 is complicated because you have to separate pinning force from other forces, where currently they are merged together.
    #3 is the best in my opinion because it is transparent to the user. Things would just work, it would make PuppetMaster less complicated, and I have a single object transformation to read from and write to.
     
  3. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    2. We are not dealing with isolated rigidbodies here, a ragdoll is a chain of joints and accelerations on one rigidbody carry on to others, extracting a source of motion from that sounds like an impossible calculation.

    3. I have actually tried to make this work without a dual rig, but it is not as simple as you'd think. There is currently no way to read the animated pose before Mecanim applies it to the bone transforms. That means Mecanim overwrites your ragdoll each time it updates (moving all the transforms and colliders, an expensive procedure). So we'd have to store the ragdoll state, all positions, rotations and velocities and move the ragdoll back to that in FixedUpdate so physics could continue with what it had in the end of the previous simulation step. Then, in LateUpdate, the entire character has to be moved (a very expensive procedure) for the 4th time: 1 - Mecanim, 2 - moving to last solved physics state, 3 - physics, 4 - interpolating from physics to animation (mapping).
    So you see, even if you had one bone transform to read, it would still be in different places in Update, FixedUpdate and LateUpdate, so using a single rig would not solve that problem, just make everything slower. I tested the performance back when I experimented with different designs and the dual rig was twice as fast.

    In the future, if Mecanim will ever have something like a "read only" mode, where we could read it's internal state without it actually applying it to the bones, I'll certainly switch for a single rig, I agree with you, it would obviously be so much simpler for users to understand and use.
     
  4. Griffo

    Griffo

    Joined:
    Jul 5, 2011
    Posts:
    700
    @Partel-Lang Hi, have you plans to add quadruped support to the Ragdoll creator ?
     
  5. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Yes, but got other things prioritized before I get to that.
    In the meanwhile, you can use BipedRagdollCreator for quadrupeds too, it will take some editing though with the RagdollEditor to make it right.

    Cheers,
    Pärtel
     
    Griffo likes this.
  6. chaneya

    chaneya

    Joined:
    Jan 12, 2010
    Posts:
    416
    Partel,

    I have another request regarding props. Several months ago you added a bool to Props called Force Layers because Puppetmaster was forcing layer changes to props in PuppetMaster so thanks for doing that.

    This is a similar situation except PuppetMaster is re-enabling the prop PickUpTrigger once it has been dropped. This is a problem I have been working around by just using if/then return statements if I want to ignore the Trigger collider but it would be much simpler if I could control when the Trigger gets re-enabled upon drop. There are numerous scenarios where I want that trigger to be disabled for certain amounts of time or under certain circumstances.

    It took me some time to figure out where in your code you re-enable the prop trigger but it happens when
    Code (CSharp):
    1. puppetMaster.RemoveMuscleRecursive(lastProp.muscle, true, false, MuscleRemoveMode.Sever);
    is called in PropRoot.

    I further traced what you are doing to OnMuscleRemoved in BehaviorPuppet,cs which calls SetColliders in BehaviorPuppetStateSwitching which ultimately re-enables all colliders on the prop when it has been dropped.

    As usual I could fix this but then my changes would be overridden with PuppetMaster updates.

    Thanks
    Allan
     
  7. Fairennuff

    Fairennuff

    Joined:
    Aug 19, 2016
    Posts:
    88
    Hi Partel!
    I've been heavily using Final IK in my project so thanks again for that! Now I'm adding in puppet master in an attempt to get some really solid hit reactions going on. This is a VR game, and you can sword fight with enemies. I've been playing around with puppet master/tweaking reactions for a few days now and can't get what I'm looking for. Here are my few dillemas:
    I looked at your punching demo which is effectively what I want. I don't want the enemies to fall down when I hit them. Just cancel their animation/attack and react appropriately to the weapon hitting them. Problem with copying the punch demo is their attacks are no longer accurate because of the unpinning of the upper body. They start to look a bit flimsey. I'd like the attacks to be 1:1 with the animations but when hit get jarred about a bit without really using animations if possible.

    Any suggestions on how to obtain this would be appreciated.

    Thanks again. You sir make some Extremely solid assets!
     
  8. Deviarc

    Deviarc

    Joined:
    Sep 4, 2014
    Posts:
    24
    Hey Partel!
    It's possible to freeze a group of muscles or a individual muscle to ignore the animation and make it stay in a desired position? Like, I'm interacting with the puppet with a raycast when the user press the mouse button and adding force to the muscle using the broadcaster while the user is with the mouse button pressed, when the user let the mouse button up I would like to freeze the muscle position to where he moved.
    Also, what should I change to decrease the spread of the force on the puppet?

    Ty a lot! Your asset is really nice!
     
  9. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Hey,
    Thanks for the info, looks like you found a bug. Please import this patch. It will prevent trigger colliders from being added to PuppetMaster management at all.

    Hey,
    You could make a script that listens to behaviourPuppet.OnCollisionImpulse delegate. If there is a hit with the weapon, set pin weights for the upper body to 0, then keep lerping them back to 1.

    Hey,
    Did you mean you needed to stop animation on a certain body part?
    You could make a script that stores the localRotations of the bones (not the muscles) in PuppetMaster.OnRead as they are animated; Then, when you need to disable animation on some bone(s), set the localRotations of those bones to what you stored in the same PuppetMaster.OnRead.

    Cheers,
    Pärtel
     
  10. Deviarc

    Deviarc

    Joined:
    Sep 4, 2014
    Posts:
    24
    Ty for the answer Partel.
    Yeah, I want to stop the animation on a certain part and kind freeze the part I moved. Like the player is dancing, when I click on his hand and move it up, it would stop the animation on the arm and let it move freely, when the player is not dragging/clicking anymore it would make the hand stay on that position.
    You suggested to disable the animation on some bones, to achieve this I would need to use the AddMixingTransform from Unity? And when I detect that the user input is done I get the localRotations for the bones and apply it again? I didnt understand what I should do.
    Other thing I was trying was to use the same method from the Handling example to keep the hand on a desired position, but it's probably a bad approach.

    Ty for the help!
     
  11. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Oh, I see, you need to lock the hand to a certain world space position... In that case, call puppetMaster.SetMuscleWeightsRecursive(HumanBodyBones.LeftUpperArm, 1f, 0f); (if it's not a Humanoid, use another override of SetMuscleWeightsRecursive or just set muscle.props.pinWeight to 0 for the muscles that you need to unpin.
    Then make a new gameobject, move it to the place you need to lock the hand to, add a kinematic Rigidbody and a Joint that connects it to the hand.

    Another solution would be to use IK to lock the hand to that world space position.

    Best,
    Pärtel
     
  12. Deviarc

    Deviarc

    Joined:
    Sep 4, 2014
    Posts:
    24
    Ty a lot Partel!
    It worked really nice, I was almost doing this by myself but I didnt add a Joint on the new game object.
    The only problem now is that the collider's are not really matching the position, there is a little offset between the puppet master collider and the rig object. For example, if I move the hand up and lock it on some position, it's all good, but the colliders have a little offset on the Y axis, making it be a little higher than the desired. Anything I can do to minimize this?
    Another question is that sometimes I make the target for the hand be a little far, this was causing the joint to be a little far from the other's in the arm and was causing some fighting, I solved this checking for the distance between the joints and moving the target towards the parent, it's working now, just wanted to make sure it's a ok solution.
    Ty for the help!
     
    Last edited: Mar 14, 2017
  13. Yoko_

    Yoko_

    Joined:
    Apr 17, 2014
    Posts:
    11
    Hi Partel!
    I have a question about a hierarchy problem.

    -Main gameobject (Navmesh, main script, etc...)
    ---child gameobject (Animator, mover script, etc...)
    ---PuppetMaster
    ---Pilot behaviours

    At runtime it's my main object that is moving and not this child gameobject, but when there is an explosion the child gameobject is controlled by the puppet behaviour and get some local offset that I don't want. Is there an easy way to redirect the movement on the main gameobject?

    Thanks
     
  14. tapawafo

    tapawafo

    Joined:
    Jul 25, 2016
    Posts:
    170
    I have a quick question:

    Is it bad practice to add additional colliders to the puppet's ragdoll limbs? Say I have a large pauldron, added as armor in runtime, and thus want to create a collider on the upper arm/shoulder of the puppet to match - would this work? Or is there a better method?

    Thanks.
     
  15. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Hey,
    It's just the general crappiness of joints in PhysX. You can improve the accuracy if you increase solver iteration count, increase the mass of the hand, disable preprocessing on the joints.

    It's also possible, if you have Final IK, to use IK after PuppetMaster has updated, to make cosmetic adjustments to the final pose to have 100% accuracy, that would not move the colliders though, just what you see.

    Hey,

    You should have NavMeshAgent on the same gameobject that has the animator and mover scripts, that is your character controller. The Main gameobject is basically just a folder for your character, it should not be moved.

    There are alternative ways to set up that hierarchy though.
    The main thing is that PuppetMaster must not be parented to your character controller, because the ragdoll has to be moved around by physical forces only. You could parent it to the controller, but add a line to your script that unparents it after instantiation and destroys it in OnDestroy(). So that would look like this:

    - character controller (NavMeshAgent, Animator, main script...)
    - PuppetMaster
    - Behaviours

    Code (CSharp):
    1. void Start() {
    2. puppetMaster.transform.parent = null;
    3. }
    4.  
    5. void OnDestroy() {
    6. if (puppetMaster != null) Destroy(puppetMaster.gameObject);
    7. }
    Hey,
    Yes, compound colliders are supported. You'll have to call muscle.UpdateColliders() though after you add anything in runtime.

    Cheers,
    Pärtel
     
    tapawafo likes this.
  16. Yoko_

    Yoko_

    Joined:
    Apr 17, 2014
    Posts:
    11
    Ok, in this case I'll try to adapt the hierarchy as you mentioned, thanks a lot and congrats for the great tools you provide!
     
    Partel-Lang likes this.
  17. Deviarc

    Deviarc

    Joined:
    Sep 4, 2014
    Posts:
    24
    Hey Partel, ty for the help!
    Got it working. Will check if we have Final IK here and give a try if yes.
    On a different topic, is there any way I can know when the Puppet is about to lose balance?
     
  18. FuzzyShan

    FuzzyShan

    Joined:
    Jul 30, 2012
    Posts:
    182
    anyway to move or rotate arms of my puppet via physics(Torque, or something), maybe joint target's angular velocity?
     
  19. Fairennuff

    Fairennuff

    Joined:
    Aug 19, 2016
    Posts:
    88
    Hi Partel,

    I think I've almost got my system locked in thanks to Puppet Master. One issue I'm having is with blocking enemy attacks in my VR game. I'd like when the enemy weapon is blocked to weaken their arm a bit so you can effectively "hit" their weapon very hard to throw them off. I know normally I should do this using the Prop Template but I'm not certain I can since I'm using FinalIK's interaction system to have enemies pick up weapons and interact with them. I'd have to rebuild a whole lot of stuff to make both work (I tried to but the interaction no longer sets the grab points and so the enemies no longer hold their weapons correctly at all).

    To work around this I have an on collision event for the weapon that if it hits a player weapon it loosens the arm muscles a bit using ( puppetMaster.SetMuscleWeightsRecursive(HumanBodyBones.RightUpperArm, 0, 0, 1, 0).
    However, since I have the puppet Behavior set to unmapped and the puppetMaster component set to Active I was wondering if there is a way to only activate/set the specific muscles to be active. while leaving everything else pinned. Maybe I'm just missing something but I'm trying to keep 100% animation accuracy while still being able to activate the rag doll on hit and on block, with there being specific settings/limitations on the weapon block event.

    Thanks!
     
  20. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Hey,
    The puppet will lose balance if muscle.positionOffset is greater than a certain distance (knockOutDistance multiplied by the knock out distance multipliers in the group overrides), so I guess you could check that distance.

    Only when the puppet is unpinned, then you can use AddForce/Torque just like you normally would. If pinned, the pinning will work against the forces you apply.

    Hey,
    You can have full control over mapping weights if you set BehaviourPuppet normal mode to "Active".
    Then you can use muscle.state.mappingWeightMlp, set it to 0 to have full animation accuracy. If you detect a collision (using behaviourPuppet.OnCollisionImpulse delegate), you can temporarily blend in mapping for select muscles (use muscle.childIndexes and parentIndexes to find child and parent muscles for each muscle).

    Pinning could be handled the same way. If there is a collision with the weapon, set muscle.props.pinWeight to a lower value and blend them back in to resume normal behaviour.

    Best,
    Pärtel
     
    tapawafo likes this.
  21. SammmZ

    SammmZ

    Joined:
    Aug 13, 2014
    Posts:
    173
    I think it's something very basic, but I search this topic and don't find any explanation. Here you can see a target skeleton, ragdoll and the model. Mapping/pin/muscle weight = 1. Ragdoll colliding with the ground object and pushing up, but the model don't completely follow the ragdoll and pass through obstacle. What should I do for more precise control of model behavior?

     
  22. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Hey,
    Expand the muscles in PuppetMaster and enable "Map Position" for all leg and foot muscles.

    Cheers,
    Pärtel
     
  23. SammmZ

    SammmZ

    Joined:
    Aug 13, 2014
    Posts:
    173
    Great, thanks! Now it works much better. But is there a way to force it respect the angles? To avoid weird rotations like this? Ragdoll seems to be setuped properly, but it still rotates dramatically

     
  24. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Do you have "Angular Limits" enabled in PuppetMaster?
     
  25. SammmZ

    SammmZ

    Joined:
    Aug 13, 2014
    Posts:
    173
    Yes, looks so
     
  26. GeorgeZZ

    GeorgeZZ

    Joined:
    Aug 31, 2014
    Posts:
    8
    Hi, Partel
    I'm using the "Behaviour Puppet with fall" copy from Puppet Extended scene.
    I found puppet is going to "Fall" only been knock down, but I also want puppet go to fall state in other situation.
    For example, when my character walk over a cliff I want puppet switch into fall.
    I didn't find any similar demo scene and I read Class Reference but I still can't find any clue.
    I already have raycast to detect height difference I guess I just need to tell "Behaviour Puppet" to loss balance, or I just need to switch on "Fall". But I'm not sure how to do that.
    Please give some advice to help me start, thanks.
     
  27. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Hey,
    Does it improve if you increase Solver Iteration Count? It's probably just the general crappiness of joints in PhysX.

    Hey,
    Just call
    Code (CSharp):
    1. behaviourPuppet.SetState(BehaviourPuppet.State.Unpinned);
    when you detect the character falling over the cliff via raycasting or something else.

    Cheers,
    Pärtel
     
  28. GeorgeZZ

    GeorgeZZ

    Joined:
    Aug 31, 2014
    Posts:
    8
    Thankyou, it's working.
     
  29. chaneya

    chaneya

    Joined:
    Jan 12, 2010
    Posts:
    416
    Partel,

    I just upgraded to Puppet Master .6 and my Behavior Puppet Collision Resistance Multipliers are no longer functional.

    They have no effect at all on whether or not the character is unbalanced.

    I see in the Change log that you say you may need to tweak the Collision Resistance but I'm referring to the Collision Resistance Multiplier array in Behavior Puppet. Before upgrading I had objects with Layers DebrisLarge with Multiplier set to 5 to allow unbalancing. I can set that to any value like 5000000 and the character is still unbalanced. So the Multipliers have no effect at all in determining unbalancing.

    Thanks
    Allan
     
  30. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Hey,
    Actually it is another thing causing this problem. In earlier versions puppets were only unpinned if a muscle drifted too far from its target and had more than 0.5 of damage. In 0.6 it will be unpinned if too far and any damage at all. So even a collision with resistance of 50000000 will enable the puppet to be unpinned if a muscle drifts too far.
    It was changed because requiring 0.5 damage would mean sometimes the muscles would get unrealisticly far from their targets and still not unpin the puppet because they did not have enogh damage.

    But I understand the new problem it creates. I added a "Min Collision Impulse" to BehaviourPuppet, that will discard collisions with smaller impulse than that value so large multipliers will work again. Set multiplier value to Mathf.infinity to disable damaging by a layer completely. Here's the patch.

    It will also improve the performance as tiny collisions will just not be processed anymore. :)

    Cheers,
    Pärtel
     
  31. JoshGreen

    JoshGreen

    Joined:
    Mar 16, 2017
    Posts:
    28
    This looks Really Great!! I normally make 2D cartoony games but after seeing this I'm going to start thinking about how I could use this!
     
  32. chaneya

    chaneya

    Joined:
    Jan 12, 2010
    Posts:
    416
    Partel,

    Thank you very much. :) As usual, incredible service with your products. :) And the patch worked and I can now once again control when my character is unbalanced by using layers and multipliers in the Collision Resistance Multipliers array.

    Ok so I have a question and a suggestion:
    1. How does Collision Threshold now differ from Min Collision Impulse because the tool tip for those two properties is now almost identical. Looking at the code, I see in BehaviorPuppetDamage that we basically return out of OnMuscleCollisionBehavior if impulse <= minCollisionImpulse which prevents Upin that occurs further below in the method. And CollisionThreshold is used in GetImpulse and that will return out of that method if our impulse.sqrmagnitude is less than CollisionThreshold. So is it a true statement to say that CollisionThreshold refers to only the impulse value itself used to determine damage and minCollisionImpulse refers to whether or not the character is unpinned?

    My suggestion is that you may want to try and think of a way to include a debugging option of some kind for collisions, damage, resistance, impulse, unpinning etc. Right now the only debug option (and it's a nice feature) is to show a visual of the Target Pose in PuppetMaster. But there is a ton of stuff going on in BehaviorPuppet that is wonderful but very confusing and the tool tips don't really do justice to what those properties are actually doing. If there was a debug option in behaviorPuppet that you could select to bring up an onscreen menu that provided real time debug.logs for impulse values, collision information, distance from target, damage, state of muscles and puppet.....this would be incredibly helpful. Right now my only option is to track down all of these variables in your code and then place my own debug.logs in order to get a handle on what they do and how they lead to damage and unpinning/unbalancing the character.

    Thanks
    Allan
     
    Last edited: Mar 27, 2017
  33. chaneya

    chaneya

    Joined:
    Jan 12, 2010
    Posts:
    416
    Partel,

    I spoke a little too soon. I use the OnCollisionImpulse events to determine how my character reacts to different terrain objects as well as damage from enemy props. If he is walking on ice, he will slip and fall if the resistance value for ice layer is within resistance range. If he is running through small debris and colliding with the smallDebris layer, I use OnCollisionImpulse to make him trip with animations without unpinning. If he hits a large piece of debris by colliding with LargeDebris layer, I will make him trip and unpin him etc. The problem is when I set the MinCollisionImpulse to a value like 1.5 in order to prevent PlayerRagdoll to EnemyRagdoll colisions causing unpinning, I am also defeating the ability to get an event call for walking on ice.

    My point is, in order to get a call to the OnCollisionEvent, I have to unpin the character. But there are times I want to have damage to the character or fire animations based upon collisions without having the character become unpinned. I was previously able to achieve that using layers and multipliers to resistance but that appears to no longer be the case.

    PS: It turns out I can fix my problem by moving if (OnCollisionImpulse != null) OnCollisionImpulse(m, impulse); above the check for minCollisionImpulse in OnMuscleCollisionBehavior in BehaviorPuppetDamage.cs. Is there any downside to moving the event call above the minCollisionImpulse check.

    Thanks

    BehaviorPuppet.PNG

    Code (CSharp):
    1.   void OnCollisionImpulse(MuscleCollision m, float impulse)
    2.     {
    3.         Debug.Log("CollisionManager" + "  " + impulse);
    4.         if (m.collision.contacts.Length == 0) return;
    5.         int layer = m.collision.gameObject.layer;
    6.  
    7.         #region Ice Layer
    8.         if (MyLayerMaskExtensions.Contains(layerMaskIce, layer))
    9.         {
    10.            // float collisionAmt = m.collision.impulse.sqrMagnitude;
    11.             //if (impulse < minCollisionImpulseIce) return;
    12.             if (playerRigidbody.velocity.magnitude < maxVelocityToAvoidSlide) return;
    13.  
    14.             puppetTransIce = behaviorPuppet.puppetMaster.muscles[m.muscleIndex].target;
    15.             if (puppetTransIce == animator.GetBoneTransform(HumanBodyBones.RightFoot) || puppetTransIce == animator.GetBoneTransform(HumanBodyBones.LeftFoot))
    16.             {
    17.                 if (!slidingOnIce)
    18.                     StartCoroutine(StartSlideOnIce());
    19.             }
    20.         }
    21.         #endregion
    22.  
    23.         #region DebrisSmall && DebrisLarge Layers
    24.         if (MyLayerMaskExtensions.Contains(layerMaskDebrisSmall, layer))
    25.         {
    26.             //Only StumbleSmall if we're not already stumbling and we're not in sneak mode and less than sneak dist
    27.             if (!debrisSmallStumble && !debrisLargeStumble && !animator.GetBool(animHashIDs.sneak))
    28.                 if ((playerController.navAgentDist).sqrMagnitude > playerController.sneakDistance) //This will stop from stumbling when close to navtarget
    29.                 {
    30.                     //float collisionAmt = m.collision.impulse.sqrMagnitude;
    31.                     Transform puppetTrans = behaviorPuppet.puppetMaster.muscles[m.muscleIndex].target;
    32.                     if (puppetTrans == animator.GetBoneTransform(HumanBodyBones.RightFoot) || puppetTrans == animator.GetBoneTransform(HumanBodyBones.LeftFoot))
    33.                     {
    34.                         float dotProduct = Vector3.Dot(transform.forward, playerRigidbody.velocity);
    35.                         //Debug.Log("DebrisSmall");
    36.                         if (animator.GetBool(animHashIDs.isCursorBehind) && dotProduct < 0) //Backwards
    37.                         {
    38.                             animator.SetBool(animHashIDs.stumbleSmall, true);
    39.                             animator.SetBool(animHashIDs.backwards, true);
    40.                         }
    41.                         else
    42.                         {
    43.                             animator.SetBool(animHashIDs.stumbleSmall, true);
    44.                             animator.SetBool(animHashIDs.backwards, false);
    45.                         }
    46.  
    47.                         debrisSmallStumble = true;
    48.                         StartCoroutine(StartSmallStumble());
    49.                     }
    50.                 }
    51.         }
    52.  
    53.         if (MyLayerMaskExtensions.Contains(layerMaskDebrisLarge, layer))
    54.         {
    55.             if (!debrisLargeStumble && !debrisSmallStumble && !animator.GetBool(animHashIDs.sneak)) //If player is not sneaking
    56.             {
    57.                 // float collisionAmt = m.collision.impulse.sqrMagnitude;
    58.                 Transform puppetTrans = behaviorPuppet.puppetMaster.muscles[m.muscleIndex].target;
    59.                 if (puppetTrans == animator.GetBoneTransform(HumanBodyBones.RightFoot)
    60.                     || puppetTrans == animator.GetBoneTransform(HumanBodyBones.LeftFoot)
    61.                     || puppetTrans == animator.GetBoneTransform(HumanBodyBones.RightUpperLeg)
    62.                     || puppetTrans == animator.GetBoneTransform(HumanBodyBones.LeftUpperLeg)
    63.                     || puppetTrans == animator.GetBoneTransform(HumanBodyBones.RightLowerLeg)
    64.                     || puppetTrans == animator.GetBoneTransform(HumanBodyBones.LeftLowerLeg))
    65.                 {
    66.                     float dotProduct = Vector3.Dot(transform.forward, playerRigidbody.velocity);
    67.                     // Debug.Log(collisionAmt + " " + "StartStumbleDebrisLarge");
    68.                     if (dotProduct < 0)
    69.                     {
    70.                         animator.SetBool(animHashIDs.stumbleLarge, true);
    71.                         animator.SetBool(animHashIDs.backwards, true);
    72.                     }
    73.                     else
    74.                     {
    75.                         animator.SetBool(animHashIDs.stumbleLarge, true);
    76.                         animator.SetBool(animHashIDs.backwards, false);
    77.                     }
    78.                     debrisLargeStumble = true;
    79.                     debrisSmallStumble = true;
    80.                     animator.SetBool(animHashIDs.stumbleSmall, false); //Just in case we also have a smallStumble
    81.                     StartCoroutine(LoseBalStumbleLarge());
    82.                 }
    83.             }
    84.         }
    85.         #endregion


    Thanks
    Allan
     
    Last edited: Mar 27, 2017
  34. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Omg, I actually forgot I had that Collision Threshold already, sorry. :)
    But there was a bug with that not working with the collision resistance multipliers. Please import this patch so you could just use the threshold. It also moves the OnCollisionImpulse call to the top and adds a "Collision Threshold" to the collision resistance multipliers so you will be able to override collision threshold for each layer.

    Thank you for the suggestion as well! The main problem with debugging dynamics is the factor of time. With kinematics it is much easier, everything can be looked at, investigated and debugged within a single frame, but when physics are involved, everything will change in time and it is very difficult to reproduce as there might be problems that seem to occur almost randomly.
    That said, I actually have plans for a debug tool that enables you to record a PuppetMaster session, storing ragdoll pose and all the relevant info from PuppetMaster and BehaviourPuppet frame by frame, for instance if your puppet was unpinned, it will say exactly when and for what reason. Like that you could even store it in a file and send it over to me to take a look at if you can't crack it on your own. I'll try to make it happen before PM reaches 1.0.

    Cheers,
    Pärtel
     
  35. chaneya

    chaneya

    Joined:
    Jan 12, 2010
    Posts:
    416
    Partel,

    Thanks,

    This latest patch seems to work great! And with having a Collision Threshold for each Resistance Layer, I have a little more control over the performance of those layer collisions. Additionaly, I am now receiving OnCollisionImpulse event calls regardless of whether I unpin or not so moving OnCollisionImpuse up in the method was a good idea.

    Thanks again
    Allan
     
  36. chaneya

    chaneya

    Joined:
    Jan 12, 2010
    Posts:
    416
    Partel,

    Now that we have some of those other issues worked out, I just started playing with Stagger. The Demo looks really cool. :)

    - Right now it looks like Stagger can only be initiated upon LosingBalance/Unpinning and so it sort of acts as a precursor to losing balance and is thus dependent upon losing balance. Is there any way to use Stagger as an independent state without actually losing balance. (sort of like calling behaviorPuppet.SetState();)
    - I was thinking I might be able to replace some of my stumble animations with Stagger but in order to do that I would need to be able to SetState(Stagger) and have the character recover from Stagger without losing balance.

    I guess what I'm asking is if there is a possibility of using stagger independently of Unpinning/Losing Balance?

    Thanks
    Allan
     
  37. Alfonso_CJ

    Alfonso_CJ

    Joined:
    Nov 19, 2015
    Posts:
    35
    Hey.
    I was wondering if there's a script similar to the FXCollisionBlood script but more sensitive to the environment?
     
  38. Deviarc

    Deviarc

    Joined:
    Sep 4, 2014
    Posts:
    24
    Hey Partel, I'm trying to instantiate a prefab that contains a Puppet and moves using animation root motion.
    Need to do something special? I'm keeping getting errors like this: "The position of each muscle needs to match with the position of it's target".
     
  39. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Hey,
    The first problem has already been taken care of. I'll PM you a link to the latest, you'll be able to start with Stagger disabled and start staggering simply by enabling the behaviour.

    Recovering from stagger simply by switching to BehaviourPuppet would not look realistic, I have already tried that.
    For example with a code like that, will look like a miraculous recovery:

    Code (CSharp):
    1. public BehaviourPuppet puppet;
    2.  
    3.     void LateUpdate () {
    4.         if (Input.GetKeyDown(KeyCode.R) && !puppet.enabled) {
    5.             puppet.puppetMaster.targetAnimator.CrossFadeInFixedTime("Idle", 0.3f);
    6.             puppet.puppetMaster.targetRoot.position += puppet.puppetMaster.muscles[0].rigidbody.position - puppet.puppetMaster.muscles[0].target.position;
    7.  
    8.             foreach (Muscle m in puppet.puppetMaster.muscles) {
    9.                 m.state.pinWeightMlp = 1f;
    10.             }
    11.  
    12.             puppet.enabled = true;
    13.         }
    14.     }
    He,
    Just reduce "Min Collision Impulse" in the FXCollisionBlood component (on the blood prefab).

    Hey,
    That error happens when the ragdoll has been moved away from the animated hierarchy or vice versa before PuppetMaster initiates.
    If it happens after instantiating, I'm guessing you instantiate and move the target root to some other place right in the next lines. PuppetMaster needs the ragdoll to match with the target positionally when it initiates, so if you need to move the character, move the root that contains both the ragdoll and the target.

    Cheers,
    Pärtel
     
  40. wightwhale

    wightwhale

    Joined:
    Jul 28, 2011
    Posts:
    397
    I'm having an issue when the character is doing a fall behavior and the collider will fall through the ground even though the character is still above ground rag dolling. This image has the collider half way through the ground and the collider will fully fall through the ground after rolling longer. Any insight on what might be causing this? It only seems to happen when I activate the fall behavior and it's causing unintended consequences all over.
     
  41. wightwhale

    wightwhale

    Joined:
    Jul 28, 2011
    Posts:
    397
    I figured out what the issue was. When falling the behaviour fall script was seeing my water collision layer and trying to put the collider down on that layer when the angle was higher than the .5 or whatever is set in the script.
     
    Partel-Lang likes this.
  42. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Hi all, just submitted PM 0.6.1 for review mainly to take care of all the annoying (but harmless) editor obsolete API warnings, but I've been mainly busy with PM recently so it is actually quite a substantial update. Here are the release notes:

    Version 0.6.1

    Upgrade Guide

    1. MAKE A BACKUP! Open a new scene, delete “Plugins/RootMotion” and reimport. Also reimport Final-IK if you had that in your project.
    2. If you were using any of the integration packages, reimport them from “Plugins/RootMotion/PuppetMaster/_Integration”.
    Improvements

    1. Significantly improved the accuracy at which puppets are able to follow the target animation, puppets will not fall behind as much if the character controller is moving fast.
    2. Removed muscle.offset to improve performance and stability.
    3. When Puppets are created, “Map Position” will be set true for all leg/foot muscles to improve mapping quality.
    4. Animated momentum will be transferred to the rigidbodies when switching from Kinematic to Active mode. Will enable you to set state to Dead immediately from Kinematic mode and still preserve animated momentum.
    5. Added “Collision Threshold” to the Collision Resistance Multipliers so you could override “Collision Threshold” for specific layers.
    6. Added the “Scaling” demo scene and PuppetScaling.cs script.
    7. Improved puppet behaviour activation. If all behaviours are enabled, will start with BehaviourPuppet. If not, will start with the enabled behaviour instead of forcing BehaviourPuppet. If all behaviours are disabled, will not force activation.
    8. Added “Pin Weight Threshold” to BehaviourPuppet. If a muscle has drifted farther than 'Knock Out Distance', will only unpin the puppet if it's pin weight is less than this value. Lowering this value will make puppets less likely to lose balance on minor collisions.
    9. Added “Unpinned Muscle Knockout” to BehaviourPuppet. If false, will not unbalance the puppet by muscles that have their pin weight set to 0 in PuppetMaster muscle settings.
    Fixes

    1. Trigger colliders on muscles will not be added to PuppetMaster collider management.
    2. Fixed a bug that killed the velocity of the puppet when set to Dead state when more than 1 FixedUpdate called per frame.
    3. Fixed a bug with BehaviourPuppet’s “Collision Threshold” not working with collision resistance multipliers.
    4. OnCollisionImpulse is also called for collisions with impulse below “Collision Threshold”.
    5. Fixed editor script obsolete API warnings in Unity 5.6.

    Cheers,
    Pärtel
     
  43. punkouter2019

    punkouter2019

    Joined:
    Jul 28, 2013
    Posts:
    170
    Any news on creating procedural animations? (attempting to balance...walk.. etc..) ?

    I bought it since this is the closest thing Unity has to Naturalmotion Endorphin. So wondering if you still have any plans for that in the next month.. next year?
     
  44. bcv

    bcv

    Joined:
    Sep 1, 2012
    Posts:
    34
    Hello, I'm trying to combine PuppetMaster and FinalIK but I cannot quite achieve the result I want.

    I'd like to be able to, for example, move a character's hand effector (The char has an FBBIK component) and let PuppetMaster take care of collisions. While PuppetMaster does take care of collisions the issue is that it seems hat FBBIK always has the final say in deciding where to place the character, allowing situations where if you move the end effector into a wall the character will move through the wall eventually if enough distance is between the end effector and the character.

    Is there a way to have somehow soft end effectors like when you drag rigid bodies with spring joints ?
     
  45. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Hey,
    I just added a BehaviourBipedStagger, that can be found in PuppetMaster/_Integration/Final IK package, since it requires FIK. But I'll change that in the future, make it independent of FIK. Will be working on that stuff some more in the future.

    Hey,
    The problem is that the pinning forces that are trying to make the muscles follow their targets become so stong if that target is far enough inside a collider that they'll eventually penetrate it. You'll have to reduce those pinning forces. That is what BehaviourPuppet does essentially, on collision it decreases pin weights of the colliding and it's parent/child muscles.

    Or you could do some raycasting to make sure the IK targets do not violate colliders in the first place.
     
    nixter likes this.
  46. punkouter2019

    punkouter2019

    Joined:
    Jul 28, 2013
    Posts:
    170
    What is the logic of the behaviors needing FinalIK ? How does the behavior work basically ? Is it AI? Is it moving joints based on current position ?

    Ill probably get FinalIK too. This is the particular thing that interests me the most.
     
  47. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Hey,
    It uses IK to adjust the pose that the puppet will follow, for example staggering, it will use IK to move the target pose of the legs and arms based on where the center of mass is falling towards. Planning to make those behaviours independent of FIK in the future.

    Best,
    Pärtel
     
  48. punkouter2019

    punkouter2019

    Joined:
    Jul 28, 2013
    Posts:
    170
    interesting.. I was thinking it did the opposite.. that is .. depending on the current movement is would adjust its position from the inside -> out... rather than the outside (where to put the foot) --> inside.. (does that make sense?)

    Anyways I bought them both and now shall to make an extremely simple game where you toss rocks at zombies
     
  49. shashkes

    shashkes

    Joined:
    Mar 16, 2017
    Posts:
    19
    Hi, I'm trying to fix this problem where hands go through the body of the avatar in VR
    There are collides on all the body parts (using puppet master script ragdoll creator), I made sure they are on the same layer that does have a physics interaction enabled and I've given them various materials thinking maybe a non physical material was the problem but that didn't help. Does anyone have a solution.
    the IK is by Final IK using VRIK script.

     
  50. Partel-Lang

    Partel-Lang

    Joined:
    Jan 2, 2013
    Posts:
    2,548
    Hey,
    Is the "Internal Collisions" toggle enabled in PuppetMaster?