Animator.MatchTarget()函数不能完全匹配到指定位置

问题描述:

在做unity攀爬之类的动画时会用到MatchTarget函数,但是我在用这个函数的时候,发现距离越远,

MatchTarget匹配的最终位置和给定的位置不一样。

试了好久觉得应该是动画过渡的问题。解决办法就是把startNormalizedTime设置比0大一点,比如0.2,targetNormalizedTime 设置比1小一点,比如0.8,就是匹配时间不要设为0到1

  • startNormalizedTime 开始匹配的时间,注意是单位化时间(动画开始位置是0,结束位置是1)。如果开始时间已经超过了当前动画的播放时间,会匹配下一次符合的时间。比如:startNormalizedTime传入0.2,但是当前已经播放到0.3,会匹配下一次循环的0.2的位置。
  • targetNormalizedTime 最终匹配到的单位化时间。如果值大于1,可以设置特定循环数后的位置。比如2.3代表第2次循环的30%位置。

当startNormalizedTime 设置为0,targetNormalizedTime 设置为1时,出现下面的情况:

将人物左脚匹配到红色球的位置,但是每匹配一次动画片段都不会完全到目标的位置。

于是

我把matchtarget的参数修改了一下

animator.MatchTarget(redSpherePosition,Quaternion.identity, AvatarTarget.LeftFoot, 
            new MatchTargetWeightMask(Vector3.One, 0),0.2f,0.8f);

然后就每次都能到目标位置了。

==========================================================

问题描述:

一个动画结束后转入另一个动画发生了位移

一个骑马的动画,分为上马,骑马
动画描述:      上马,人物左脚先踩到马上,高于地面(角色模型原点)0.5米
                        骑马,人物会坐在马上,左脚高于地面0.5米
然后,出现了一个问题,当unity使用matchtarget上马时(将重力和碰撞取消再用该函数,我这里是直接关闭CharacterController组件),将左脚对齐0.5米,并结束动画,此时角色已经上升了0.5米(上马动画有y轴位移)。如果应用了rootmotion的话。
当进入骑马动画时,由于骑马动画相对于原点有0.5米高,所以角色又会上升0.5米(左脚就到了1米),从而浮空。
解决办法:将上马的y baketopose,使上马时原点高度为0,取消y轴的位移
不是什么matchtarget的问题,matchtarget放在update中一直执行和在update中只执行一次效果感觉是一样的,所以用一个bool值判断以免matchtarget重复执行

//以下判断放在Update或者OnStateUpdate中
if(isReady && !animator.IsInTransition(0))
{
    //MatchTarget(...)
    isReady=false;//在动画一开始(OnStateEnter)将这个值设为true
}

==========================================================

问题描述:

使用Animator.MatchTarget前无法调整transform.position或者transform.rotation

如果在update中使用Animator.MatchTarget()、没有打开OnAinmatorMove()、勾选了Animator组件的ApplyRootMotion的时候 是可以匹配的。但是如果想在update中调整transform.position或者transform.rotation的时候,发现一点效果的没有。例如写transform.position=Vector.zero; 然后运行,角色也不会到原点去。

在上面的上马动画中,我的上马动画最后并没有刚好旋转到90度,骑到马上是歪的。所以我想在上马动画播放之前把角色的位置旋转稍微调一下

transform.position = redSpherePosition+Vector3.down*0.5f;
//使角色上马前的位置在设定的红球下方0.5米处,没有用,哪怕是
//transform.position=Vector3.zero都没用

transform.rotation = Quaternion.LookRotation(-hit.Normal) * Quaternion.Euler(0, -25, 0);
//先让角色正向面对马,然后绕y轴调整-25度,然而并无什么用,哪怕是转任意方向都没有用

animator.MatchTarget(rideableHorse_LeftFoot, Quaternion.identity, AvatarTarget.LeftFoot, new MatchTargetWeightMask(Vector3.one, 0), 0.2f, 0.8f);
//播放

大致原因:

查了一下,原因大概是说RootMotion动画根运动在update之后执行然后覆盖了手动设置的transform.position或者transform.rotation。角色的控制权就不能通过脚本来改变了。

所以就必须打开OnAinmatorMove()方法  (对应状态机中的OnStateMove()方法)  使角色的控制权交给脚本。可是此时发现角色又不能被动画根运动驱动了。(上马只播放动画,不旋转,也不发生位移)

可以在OnAinmatorMove中写

transform.position+=animator.deltaPosition;

transform.rotation*=animator.deltaRotation;

也可以直接在需要根运动改变角色位移的时候使用 ApplyBuiltinRootMotion ():

public void ApplyBuiltinRootMotion ();

描述

应用默认的根运动。

应用默认的根运动。请在 MonoBehaviour.OnAnimatorMoveStateMachineBehaviour.OnStateMove 中对您不想手动处理根运动的帧使用该方法。

还有 ApplyBuiltinRootMotion这个似乎要在OnAinmatorMove中每一帧都调用,如果用了if()开关只调用一次的话,就只会应用一帧的根运动。

    override public void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        animator.ApplyBuiltinRootMotion();
        //要一直使用,不能放在if里面,不然就只有一帧会调用这个函数,只有一帧会应用根运动

        if (isReady && !animator.IsInTransition(layerIndex))
        {
            transform.position = redSpherePosition + Vector3.down * 0.5f;
            transform.rotation = Quaternion.LookRotation(hit.normal) * Quaternion.Euler(0, -25, 0);//调整-25度,使结束上马动画进入骑马动画时正对前

            characterController.enabled = false;
            animator.MatchTarget(redSpherePosition, Quaternion.identity, AvatarTarget.LeftFoot, new MatchTargetWeightMask(Vector3.one, 0), 0.2f, 0.8f);
            
            //一个开关,是否准备好开始匹配目标
            isReady = false;
        }
    }

==========================================================

Target matching只能对Base Layer(index 0,第一个权重改不了删除不了的层)生效

本来想用动画层给动画分一下类的。。

==========================================================

遇到其他关于这个函数的问题再更新

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值