Unity之动画系统的学习(四):逆向运动学

什么是逆向运动学?

正向运动学的官网定义:

大多数角色动画都是通过将骨骼的关节角度旋转到预定值来实现的。一个子关节的位置是由父节点的旋转角度决定的。这样,处于节点链末端的节点位置是由此链条上的各个节点的旋转角和相对位移来决定的。可以将这种决定骨骼位置的方法称为前向运行学。

例如,利用现有的动画片段或者外部文件或者场景动画的方式都是前向运动学。

逆向运动学(IK)官网定义:

给定末端节点的位置,从而逆推出节点链上所有其他节点的合理位置。例如,希望角色的手臂去触碰一个固定的物体。

通过逆向运动学实现注释动画

角色视线随着鼠标而移动。

新建一个游戏对象,并创建一个Animator Controller

在这里插入图片描述

创建一个Idle动画状态,并添加相应的动画片段。

在这里插入图片描述

在Base Layer窗口勾选IK Pass来允许使用IK方式来实现角色姿态

在这里插入图片描述

使用脚本来实现角色的姿态,让角色视线随着鼠标而移动

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class IKController : MonoBehaviour {
    
    

    private Animator anim;

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

    //自动被调用
    private void OnAnimatorIK() {
    
    
        //得到鼠标位置

        // 使用主摄像机创建一根射线,射线的方向是鼠标点击的位置(从摄像头位置到鼠标点击位置的一条射线)
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

        //print(ray.origin)

        //构造一个虚拟平面,通过法线
        Plane plane = new Plane(Vector3.up, transform.position);

        //enter 设置为沿着射线,相对于它与平面的相交处的距离
        float enter = 0f;

        //平面和射线相交
        if (plane.Raycast(ray, out enter)) {
    
    
            
            //预览射线
            Debug.DrawRay(ray.origin, ray.direction*5);

            //返回射线enter距离处的点
            Vector3 target = ray.GetPoint(enter);
            
            anim.SetLookAtPosition(target);
            //调节头的权重
            //anim.SetLookAtWeight(0.3f);

            anim.SetLookAtWeight(1f, 0.5f, 0.8f,0.9f);
        }
        
    }

}

在这里插入图片描述

通过逆向运动学实现末端节点动画

让手部或足部能够够到场景中某个特定的位置。

新建角色,Target,Hint游戏物体

在这里插入图片描述

为Target创建动画

在这里插入图片描述

添加脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class IKController2 : MonoBehaviour {
    
    

    private Animator anim;

    //目标位置,手部或足部需要够到的位置
    public Transform target;

    //参考位置
    public Transform hint;

    public bool isHand=true;

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

    private void OnAnimatorIK(int layerIndex) {
    
    
        //得到末端节点
        AvatarIKGoal g = isHand ? AvatarIKGoal.RightHand : AvatarIKGoal.RightFoot;

        //得到参考节点hit
        AvatarIKHint h = isHand ? AvatarIKHint.RightElbow : AvatarIKHint.RightKnee;

        //设置IK权重
        anim.SetIKPositionWeight(g, 1f);

        //设置末端节点目标位置
        anim.SetIKPosition(g, target.position);

        //设置旋转的权重和目标朝向
        anim.SetIKRotationWeight(g, 1f);
        anim.SetIKRotation(g, target.rotation);

        //设置参考节点的权重和位置
        anim.SetIKHintPositionWeight(h, 1f);
        anim.SetIKHintPosition(h, hint.position);

    }

    void Update() {
    
    

    }
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_39520967/article/details/107383237