Unity Animation Rigging 程序化行走

Unity Animation Rigging 程序化行走

为什么要程序化行走

制作Unity行走时动画时,如果仅仅使用传统的动画系统,往往无法做到与地形完美的贴合,比如上坡时,脚下踩到石头时,效果就不太好。此时就可以考虑程序化行走啦。

效果视频

Unity Animation Rigging 程序化行走

原理

首先得明白IK,即反向运动学,其实就是根据目标的位置,推算骨骼系统各个关节的运动位置和朝向,以达到尽量靠近目标的目的。比如要拿起桌子上的苹果,人的大脑会瞬间进行计算,控制肩膀、胳膊肘、手腕等关键进行运动,最终使手触达苹果,这个过程就是IK。然后,程序化行走就是基于IK的,这需要逆向思考一下,其实程序化行走,并不是腿把身体支撑了起来,而实际上,我们控制的是身体,然后根据当前的坐标位置,判断跟身体匹配的下一步的落脚点,最后利用IK去反向计算腿部的关节。
Unity Animation Rigging 程序化行走_第1张图片
最简单的情况:以身体坐标为参考,针对每个腿,赋予一个恰当的偏移量(上图红球位置),然后朝地面发射一根射线,用来检测落脚点,然后就能根据hit.point知道落脚点的地面高度了,然后将腿部的IK目标点设置为该点,剩下的就是交给Unity引擎了,unity会根据目标点位置,还有IK的各类约束(比如有的关节会约束旋转的角度,比如人的膝盖,永远不能向前打弯),去自动计算腿部的姿态。
然后就简单了:

/* --------------------
 * 此代码挂在脚上
 * --------------------*/
private void Update()
{
    // lerp表示上一步落脚点到下一步落脚点的行进进度(0-1)
    if (lerp < 1)
    {
        lerp += walkerBody.StepSpeed * Time.deltaTime;
        if (lerp >= 1)
        {
            // 如果已经踩到新的落脚点
            transform.position = targetPos;
            oldPosition = targetPos;
            walkerBody.OnStepDone(this);
        }
        else
        {
            // 正在迈步,通过高度上增加Sin函数,则可以让脚步的位置有弧线变化。
            Vector3 pos = Vector3.Lerp(oldPosition, targetPos, lerp);
            pos.y += Mathf.Sin(lerp * Mathf.PI) * walkerBody.StepHight;
            transform.position = pos;
        }
    }
    else
    {
        // 不管身体位置如何变化,IK目标点总是设置到落脚点上
        transform.position = oldPosition;

        // 判断身体的位置移动,是否超过步长,超过就要迈步。
        if (Physics.Raycast(walkerBody.transform.position + stepOffset, Vector3.down, out RaycastHit hit,
            stepOffset.y * 2, walkerBody.GroundLayerMask))
        {
            // 左脚和右脚不能同时迈步,这里判断一下不能同时迈步的其他脚是否正在迈步。
            if (CantSimultaneous != null && CantSimultaneous.Any(other => other.IsWalking))
                return;
            if (Vector3.Distance(hit.point, oldPosition) > walkerBody.StepDistance)
            {
                lerp = 0;
                targetPos = hit.point;
            }
        }
    }
}

上面的代码是根据官方例子修改而来,然而有些不太完美的地方在于,**迈步动作太被动了。**往往身体都移动了半个步长了,脚才开始迈步,好像腿被打断了拉在后面一样。
Unity Animation Rigging 程序化行走_第2张图片
后来,在落脚点检测的时候,又增加了行进方向上的偏移,相当于身体迈步前,就朝身体运动的方向提前一点判断落脚点,然后整个动画就很舒服了。并且把迈步的机制,从“脚”移动到了“身体”。

/* --------------------
 * 此代码挂在身体上
 * --------------------*/
private void Update()
{
    Vector3 dir = new(Input.GetAxis("Vertical"), 0, -Input.GetAxis("Horizontal"));
    if (dir.sqrMagnitude > 0.25f)
    {
        Vector3 realdir = transform.TransformDirection(dir).normalized;
        Controller.SimpleMove(realdir * MoveSpeed);

        if (IsMoving)
        {
            Vector3 offset = transform.position - oldPosition;
            if (offset.magnitude > StepDistance)
                NextStep(realdir);
        }
        else
        {
            IsMoving = true;
            NextStep(realdir);
        }
    }
    else
    {
        IsMoving = false;
    }
}

最后再来个2足的机器人效果:

Unity Animation Rigging 程序化行走

继续完善

其实可以继续完善的地方还有很多,比如在传统行走动画的基础上,增加IK约束,预判障碍物形状,使用不同的翻越动画越过障碍等。

你可能感兴趣的:(Unity,unity,程序化,行走,IK,反向运动)