alt

Animator组件上有个Apply Root Motion来控制播放动画时是否启用动画自带的位移,有时候我们希望自己控制Root Motion因为动画师构建的位移更加符合角色动画,为此我们给Playable也增加RootMotion的支持。

提供支持的可能性在于Unity提供了OnAnimatorMove函数并能在这个方法内部获取到动画的位移变量,我们要把这个变量传出去但实际上只有动画播放时才回有值,这种不能直接向外界传值的情况我们可以通过事件的方式间接传参,也就是把功能方法准备好,等待OnAnimatorMove调用事件执行并将需要的位移参数(animator.deltaPosition,animator.deltaRotation)传入。

    # region RootMotion
    private Action<Vector3, Quaternion> rootMotionAction;
    private void OnAnimatorMove()
    {
        rootMotionAction?.Invoke(animator.deltaPosition, animator.deltaRotation);
    }

    public void SetRootMotionAction(Action<Vector3, Quaternion> rootMotionAction)
    {
        this.rootMotionAction = rootMotionAction;
    }

    public void ClearRootMotionAction()
    {
        rootMotionAction = null;
    }
    #endregion

对应给外界提供事件的设置、清空函数。


    /// <summary>
    /// 播放动画
    /// </summary>
    public void PlayAnimation(string animationClipName, Action<Vector3,Quaternion> rootMotionAction = null,float speed = 1, bool refreshAnimation = false, float transtionFixedTime = 0.25f)
    {
        if (rootMotionAction != null)
        {
            view.Animation.SetRootMotionAction(rootMotionAction);
        }
        view.Animation.PlayAnimation(warriorConfig.GetAnimationByName(animationClipName),speed,refreshAnimation, transtionFixedTime);
    }

    public void PlayBlendAnimaiton(string clip1Name, string clip2Name, Action<Vector3, Quaternion> rootMotionAction = null, float speed = 1, float transitionFixedTime = 0.25f)
    {
        if (rootMotionAction != null)
        {
            view.Animation.SetRootMotionAction(rootMotionAction);
        }

        AnimationClip clip1 = warriorConfig.GetAnimationByName(clip1Name);
        AnimationClip clip2 = warriorConfig.GetAnimationByName(clip2Name);
        view.Animation.PlayBlendAnimaiton(clip1, clip2, speed, transitionFixedTime);

    }

在播放动画时提供缺省参数Motion事件用于告知用根运动里的位移参数做什么。

    public override void Exit()
    {
        base.Exit();
        player.ClearRootMotionAction();
    }
    public void OnRootMotion(Vector3 deltaPosition, Vector3 deltaRotation)
    {
        Debug.Log(deltaPosition);
    }

    player.PlayBlendAnimaiton("Walk", "Run", OnRootMotion);

在移动状态里我们添加测试逻辑,在移动时输出根运动的位置变化量,同时注意状态退出时要清空RootMotion事件。

alt

此时面板上的ApplyRootMotion已经显示被脚本控制。