• Unity-动画状态机使用细节记录


    Unity动画控制器Animator功能非常强大,总结一些具体使用细节,在动作游戏中很实用;

    1.动画烘焙

    不同动画之间,可能存在角色朝向,重心高度不一致;

    可以在动画Eidt界面设置RootTransform Rotation重新烘焙旋转;

    RootTransformPosition(Y)烘焙高度,地面动作选择feet,烘焙在脚上;

    设置完烘焙必须点Apply才能生效;

    image-20220408122255534

    2.动作镜像

    有些单手动作,左右手都可以做,动画机添加bool参数,动作Inspector界面Mirror勾选Parameter;

    将bool参数设置进去,代码动态调节bool参数切换左右手;

    image-20220408123000521

    3.StateMachineBehaviour

    Unity动画机没有直接的api判断动画播放结束,StateMachineBehaviour可以做到;

    动画状态机生命周期:

    OnStateEnter

    OnStateUpdate

    OnStateExit

    创建FSMOnExit脚本继承StateMachineBehaviour,重写OnStateExit方法,监听到有退出消息向上传递方法名,在角色控制脚本中实现该方法;

    该脚本挂载在动画机中需要监听的state上;

    TIps:SendMessageUpwards效率很低,建议改成事件机制;

    public class FSMOnExit : StateMachineBehaviour
    {
        public string[] onExitMessages;
    
        override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            for (int i = 0; i < onExitMessages.Length; ++i)
            {
                animator.gameObject.SendMessageUpwards(onExitMessages[i]);
            }
        }
    }
    

    image-20220408132529631

    4.trigger累积清空

    Unity动画机的trigger有个出名的”bug“,trigger会累积1次;

    造成的效果就是,起跳后空中按跳,落地会再次起跳;

    同样攻击也会如此;

    解决办法与上述方法相同,在OnStateExit、OnStateEnter按需求重置trigger;

    也可以选中在关键帧动画事件中重置Trigger,可以实现连击时机判定(前置动作过半再次按下攻击才可连击);

    public class FSMClearSignals : StateMachineBehaviour
    {
        public string[] clearAtEnter;
        public string[] clearAtExit;
    
        override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            foreach (string key in clearAtEnter)
            {
                animator.ResetTrigger(key);
            }
        }
    
        override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
        {
            foreach (string key in clearAtExit)
            {
                animator.ResetTrigger(key);
            }
        } 
    }
    

    5.连击动作混合

    att1

    连击动作之间不需要收招,如果是同一个Layer的动作,使用官方混合,拖动时间线同时可以预览效果;

    ExitTime:该状态有多个后续连线状态,中间没有其他条件的情况下,ExitTime决定先进入的状态;

    InterruptionSoure:在混合状态时(重叠部分),该状态被打断返回的状态,默认返回Next;

    可设置Current State,Next State;

    image-20220408134021720

    6.动画Layer设置

    Layer可用隔开常规行为动作、攻击、面部表情、以及不同职业动作;

    image-20220408135916667

    创建动画层可以设置weight权重,和Mask骨骼遮罩;

    Defend层,由于防御只需要右手动作一直举盾,其他动作一致,添加RightHandMask;

    Asset面板右键Create-Avatar Mask,把不需要的骨骼都标红;

    image-20220408135837706

    层与层之间会更具weight混合——这就让我们可以通过代码来插值计算在不同之间做动画连贯处理;

    比如BaseLayer=>Attack层做了插值计算后;

    cahzhi2

    image-20220408140115570

    7.动画曲线

    动画过程中可以设置曲线,通过代码可获得曲线的值;

    比如这里,我希望攻击时,角色向前跨出一步,但是又不希望匀速滑步,要求起手时跨出一大段距离,逐渐减少,有个惯性的效果;设置如下曲线;

    代码中:通过动画机获取参数attack1hAVelocity,会返回动画时间对应的曲线值;

    model.transform.forward * mAnima.GetFloat("attack1hAVelocity");
    

    image-20220408141831283

    8.RootMotion

    有些动画播放时位置会改变,Animator动画机勾选Apply Root Motion,表示使用动画中的位移;

    Unity脚本生命周期中有一个OnAnimaRootMove,实现该方法动画中的位移只会受到脚本控制;

    image-20220408142558595

    代码中,当播放attack1hC动画时,OnAnimaRootMove累积动画中的位置,在FixedUpdate中赋予Rigidbody;

    这样可以做到前面动画曲线的效果,这种方法会更符合美术需求;

    9.onAnimationIK

    在OnAnimationIK周期方法中代码控制骨骼节点的位置;

    我就动作不符合需求且没有美术配合的时候用用;

    也有很多高级IK算法,可以模拟出各种炫酷飘逸的效果;油管大佬

    ik232

    public class LeftArmAnimaFix : MonoBehaviour
    {
        private Transform leftArmLow;
        [SerializeField]private Vector3 offset;
        private Animator mAnima;
    
        private void Start()
        {
            mAnima = GetComponent<Animator>();
            leftArmLow = mAnima.GetBoneTransform(HumanBodyBones.LeftLowerArm);
        }
    
        public void OnAnimatorIK(int layerIndex)
        {
            leftArmLow.localEulerAngles += offset;
            mAnima.SetBoneLocalRotation(HumanBodyBones.LeftLowerArm,Quaternion.Euler(leftArmLow.localEulerAngles));
        }
    }
    
  • 相关阅读:
    MIPI CSI-2笔记(6) -- Low Level Protocol(D-PHY物理层包头ECC)
    基于静电放电算法优化概率神经网络PNN的分类预测 - 附代码
    【数据恢复】.360勒索病毒|金蝶、用友、OA、ERP等软件数据库恢复
    一文带你详细了解浏览器安全
    Linux程序的加载过程
    Node.js
    【算法练习Day16】找树左下角的值&&路径总和&& 从中序与后序遍历序列构造二叉树
    软件架构设计
    如何为你的WSL2更换最新的6.5.7kernel
    MATLAB 运算符
  • 原文地址:https://www.cnblogs.com/littleperilla/p/16116983.html