Unity---动画系统学习(5)---使用MatchTarget来匹配动画

1. 介绍

做好了走、跑、转弯后,我们就需要来点更加高级的动画了。
我们使用自带动画学习笔记2中的翻墙Vault动画,来控制人物翻墙。


在[动画学习笔记4](https://www.cnblogs.com/Fflyqaq/p/10777793.html)的基础上添加Vault动画。 ![](https://img2018.cnblogs.com/blog/1355434/201904/1355434-20190427134224868-1278682975.png) 添加一个参数**Vault**,设置当人物处于跑的状态并且Vault参数为true时会自动翻墙。 ![](https://img2018.cnblogs.com/blog/1355434/201904/1355434-20190427134439683-1900554000.png)

2. 问题

问题1:如何判断当人物跑向墙体时,在一定范围内触发跳跃动画?
问题2:跳跃动画如果只是播放的话,很可能会出现穿模现象,如何让人物的手正好按着墙翻过去呢?

2.1 问题1

解决思路:

  1. 新建一个坐标用于存储跳跃时,手要按下的位置
  2. 判断人物是否处于跑的状态
  3. 使用射线检测,当人物正前方一段距离为要跳跃墙面时,获取此物体最上面的点为要按下的点

下面新方法的介绍:
anim.GetCurrentAnimatorStateInfo(0).IsName("LocalMotion"):判断当前播放的动画是否为LocalMotion动画,返回bool

public static bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo,float maxDistance = Mathf.Infinity):射线起点,射线方向,碰撞物体信息,检测最大距离

	private Animator anim;
	private Vector3 matchTarget = Vector3.zero; //匹配手按下的位置

	void Start () {
        anim = gameObject.GetComponent<Animator>();
	}

	void Update()
	{
		ProcessVault();
	}

	private void ProcessVault()
    {
        bool isVault = false;
        //只有物体在Blend Tree动画下才需要检测,0是层数,默认状态是第0层
        if (anim.GetFloat(speedZID) > 3 && anim.GetCurrentAnimatorStateInfo(0).IsName("LocalMotion"))
        {
            //射线起点,射线方向,碰撞物体信息,检测最大距离
            //起点在脚部向上一点,射线方向是人物正前方,
            RaycastHit hit;
            if (Physics.Raycast(transform.position + Vector3.up * 0.3f, transform.forward, out hit, 4.0f))
            {
				//Obstacle是要跳跃墙面的tag
                if (hit.collider.tag == "Obstacle")
                {
                    //只有一定距离时才会触发,不然贴着墙走就会跳了
                    if (hit.distance > 3)
                    {
                        Vector3 point = hit.point;
                        //修改碰撞点y坐标为:碰撞体的y位置+碰撞体的尺寸高度
                        point.y = hit.collider.transform.position.y + hit.collider.bounds.size.y;
                        matchTarget = point;

                        isVault = true;

                    }
                }
            }
        }
        anim.SetBool(valutID, isVault);
    }

2.2. 问题2

问题2的解决方法就要靠我们的MatchTarget了,上面获取了手要按下的点后,只需要让手按在这里就行了。

anim.IsInTransition(0):该层动画是否在进行动画的过渡,返回bool

void MatchTarget (Vector3 matchPosition, Quaternion matchRotation, AvatarTarget targetBodyPart, MatchTargetWeightMask weightMask, float startNormalizedTime,float targetNormalizedTime)
参数1:要匹配点的位置。
参数2:匹配的目标点旋转角度的四元数(不太懂,写Quaternion.identity)。
参数3:要匹配的人物位置(AvatarTarget.LeftHand表示人物骨骼的左手)
参数4:position和rotation占的权重(因为我们只匹配位置,所以如下设置位置权重1,旋转权重0)。
参数5:从动画的什么时候开始匹配。
参数6:什么时候结束(这需要自己慢慢调试,多试试就好了)

	private void ProcessVault()
    {
        if (anim.GetCurrentAnimatorStateInfo(0).IsName("Vault") && anim.IsInTransition(0) == false)
        {
            //当正为跳墙的状态时候触发
            anim.MatchTarget(matchTarget, Quaternion.identity, AvatarTarget.LeftHand, new MatchTargetWeightMask(Vector3.one, 0), 0.32f, 0.4f);
        }
    }
原文地址:https://www.cnblogs.com/Fflyqaq/p/10778608.html