Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Animator gravity weight

Discussion in 'Editor & General Support' started by BreakfastBrew, Mar 28, 2019.

  1. BreakfastBrew

    BreakfastBrew

    Joined:
    Jan 27, 2016
    Posts:
    2
    I've been trying to wrap my head around as to why gravity with root motion is so difficult. There's this hidden curve that's not documented at all except for one small line that simply says

    "Note: the Animator.gravityWeight is driven by Bake Into Pose position Y. When enabled, gravityWeight = 1, when disabled = 0. gravityWeight is blended for clips when transitioning between states."

    That's great. I'll set it to one at the start! Except I can't. The only thing I can do is read what gravityWeight is and it's by default set to 0.

    Instead I have to hack apart each animation and manually set a curve to a constant 1 and call it GravityWeight, notice the capital G. Now my root motion has gravity! Except it doesn't with blend trees. As you recall, I have set the weight of gravity to 1 and every frame I check what gravityWeight is and well, it IS set to 1. So what gives? What exactly is controlling root motion gravity and why is not accessible?
     
  2. wang-li

    wang-li

    Joined:
    Apr 19, 2019
    Posts:
    1
    I have the same question as well.
    Why isn't there any information on this annoying bug?
     
  3. tcz8

    tcz8

    Joined:
    Aug 20, 2015
    Posts:
    504
    Great, also trying to get this to work on a blendtree.

    I'm going to make sure all the anims in the blendtree have a GravityWeight curve and if that fails I'll try setting animator.gravityWeigh = 1 within a StateMachineBehavior during OnStateEnter,
    OnStateUpdate or OnStateMove.

    Also I would imagine your rigidbody's useGravity should be checked and isKinematic may interfere with it.

    EDIT: OK I just tested this out and got it to work so lets confirm a few things:
    1. You need to name the curve GravityWeight capital G (to be fair I didn't test lower g)
    2. If using a blend tree make sure you add the curve to all animations in the tree
    3. My animator's update method is set to Normal
    4. My animator's cull method is set to Cull Update Transforms
    5. My animations' Root transform position (Y) is set to bake into pose
    6. My Rigidbody is set to Kinematic and Use Gravity is set to false but I do use Unity's Character controller which applies gravity by itself.
    You may have to play around with these settings depending on your Rigidbody's settings.

    Once you got the gravity working you will end up with the normal gravity behaviour. Which means your character will go down instead of floating but it will bounce when walking/running downhill.

    This is another problem in itself, look at this video to gain an understanding of the issue and the proposed fix:


    I don't think this fix will work as is for root motion driven navigation because of the execution order, animations are applied after Update() checkout https://docs.unity3d.com/Manual/ExecutionOrder.html.

    It should work if you do it in LateUpdate() but I will try doing it within a StateMachineBehavior so I can modify the root motion data within OnStateMove which you get a hold of using
    Code (CSharp):
    1. animator.deltaPosition;
    modify it and then apply it with
    Code (CSharp):
    1. charCtrl.Move(deltaPosition)
    if using Unity's Character controller. Hopefully this will allow more control over what's going on but may be overkill.

    BTW You can also mess around with the root rotation in there using:
    Code (CSharp):
    1. animator.deltaRotation;
    and
    Code (CSharp):
    1. transform.rotation *= deltaRotation
    which can be very useful for other things (Like scaling the rotation of an animation to end up at an exact position).

    FYI: If you go the StateMachineBehavior route, the difficult part is getting hold of game objects within the scene (like your player and its scripts). You can try setting a Static variable in your character script's class to reference its instance or iterate over all "StateMachineBehaviors" within the animator to set a reference to your character script.

    Also, when modifying those values (deltaPosition and deltaRotation) take note that they are "deltas" meaning they represent the change that needs to be applied to the current position and rotation.
     
    Last edited: Dec 30, 2019
    Olipool, Keywise and Eudaimonium like this.
  4. Qixiant

    Qixiant

    Joined:
    Apr 22, 2019
    Posts:
    3
    U can use Animator.BindStreamProperty(_animator.transform, typeof(Animator), "GravityWeight") in a monobehaviour awake or start... then it will works....
     
  5. tcz8

    tcz8

    Joined:
    Aug 20, 2015
    Posts:
    504
    I will take a look at that suggestion thank you @Qixiant

    BTW I found a better solution than adding the GravityWeight curve to all anims.

    My main navigation is on layer 0 and all my ungrounded states (Jump, falling, etc) are on other layers, so I created an "UNGROUNDED" state on layer 0 that I switch to every time the player is ungrounded.

    That state has an empty animation that only has the "GravityWeight" curve on it. Since layers blend together, it successfully enables gravity for any animation playing at the same time the state is active.

    It saved me a lot of time.