Unity IK 反向动力学 学习笔记

目录

[Unity IK 反向动力学](#Unity IK 反向动力学)

[ik 示例代码:](#ik 示例代码:)


Unity IK 反向动力学

"IK是Inverse Kinematic的缩写,也就是反向动力学。是根据骨骼的终节点来推算其他父节点的位置的一种方法。比如通过手的位置推算手腕、胳膊肘的骨骼的位置。"

适用的场景:
比如角色需要拿各种不同的东西,让角色的手能符合各种不同的东西的握持位置,这样就不用针对每种不同的东西单独制作动画了!"

其他的用途其实还有比如:角色的头的旋转,这样可以和你视角的方向一致。角色的脚的位置,这样可以让角色踩在地面跟贴合。 "

"对对对,我只想到手了。那还有其他的么?"

"**Unity中IK能设置的部位就是5个,分别是:头、左右手、左右脚。**所以没有其他部位的IK了,我们常见的其实也都是这些。"

参考:[专栏精选]Unity动画系统的IK详解 - 知乎

ik 示例代码:

Unity3d 中实现 Fabrik IK - 知乎

Fabrik 是一种是现实逆向动力学 IK (Inverse Knematics)的迭代算法,迭代次数越多效果越好。逆向动力学一般可以用来实现骨骼动画。这里就以实现骨骼动画为例来说明。

每次迭代都包括一次正向迭代和反向迭代。

正向迭代是指从骨骼的控制点开始,以控制点的位置不变,并以他为基准,其他点进行移动;反向迭代则是使骨骼根部的位置为初始位置不变,其他点以他为基准进行移动。这样进行了一次迭代后所有点即向控制点进行了移动又保持的根骨骼的位置不变,从而实现了 IK 的效果。

算法描述:

1.记录根节点的初始位置、控制点位置以及各点之间的距离。

2.正向迭代:把末端节点设置到控制点位置。末端节点的前一节点向末端节点移动到距离为初始记录的距离,如此向后类推到根节点。

3.反向迭代:把根节点设置到根节点初始位置。根节点的后一节点向根节点移动到距离为初始记录的距离,如此向前类推到末端节点。

4.完成设点的迭代次数后,更新节点位置。

示例代码:

cs 复制代码
 public class FabrikIK : MonoBehaviour
{
        public bool applyIK;

        public Transform ikPos;

        public Transform[] controlPoints;

        public Transform[] limbs;

        public int iterateTimes = 1;

        private List<float> _dists;

        private int _lastPointIndex;

        private Vector3 _rootPos;

        private int _interatedTimes = 0;

        private void Start()
        {
            _dists = new List<float>();

            _rootPos = controlPoints[0].position;

            _lastPointIndex = controlPoints.Length - 1;
            
            //记录初始位置
            for (int i = 1; i < controlPoints.Length; i++)
            {
                float dist = Vector3.Distance(controlPoints[i].position, controlPoints[i - 1].position);
                _dists.Add(dist);
            }
        }

        private void LateUpdate()
        {
            if (applyIK)
            {
                _interatedTimes = 0;
                while (_interatedTimes < iterateTimes)
                {
                    if (Vector3.Distance(controlPoints[_lastPointIndex].position, ikPos.position) > 0.1f)
                    {
                        ForwadIteration();
                        BackwardIteration();
                        LimbsUpdate();
                    }
                    _interatedTimes++;
                }
            }
        }

        //正向迭代
        private void ForwadIteration()
        {
            controlPoints[_lastPointIndex].position = ikPos.position;//从控制点开始

            for (int i = _lastPointIndex - 1; i >= 0; i--)
            {
                Vector3 dir = (controlPoints[i].position - controlPoints[i + 1].position).normalized;
                controlPoints[i].position = controlPoints[i + 1].position + dir * _dists[i];
            }
        }
        
        //反向迭代
        private void BackwardIteration()
        {
            controlPoints[0].position = _rootPos;//从根部开始

            for (int i = 1; i < controlPoints.Length; i++)
            {
                Vector3 dir = (controlPoints[i].position - controlPoints[i - 1].position).normalized;
                controlPoints[i].position = controlPoints[i - 1].position + dir * _dists[i - 1];
            }
        }

        private void LimbsUpdate()
        {
            for (int i = 0; i < limbs.Length; i++)
            {
                if (limbs[i] != null)
                {
                    Vector3 mid = Vector3.Lerp(controlPoints[i].position, controlPoints[i + 1].position, .5f);
                    Vector3 dir = (controlPoints[i + 1].position - controlPoints[i].position).normalized;
                    limbs[i].position = mid;
                    limbs[i].right = dir;
                }
            }
        }

#if UNITY_EDITOR
        private void OnDrawGizmos()
        {
            if (controlPoints != null && controlPoints.Length > 0)
            {
                Gizmos.color = Color.blue;

                for (int i = 0; i < controlPoints.Length; i++)
                {
                    if (controlPoints[i] != null)
                    {
                        Gizmos.DrawSphere(controlPoints[i].position, 0.2f);
                    }
                }
            }
        }
#endif
}
相关推荐
励志不掉头发的内向程序员8 分钟前
【Linux系列】掌控 Linux 的脉搏:深入理解进程控制
linux·运维·服务器·开发语言·学习
光影少年1 小时前
云计算生态及学习方向和就业领域方向
学习·云计算
好奇龙猫1 小时前
[AI学习:SPIN -win-安装SPIN-工具过程 SPIN win 电脑安装=accoda 环境-第四篇:代码修复]
人工智能·学习
luckyPian2 小时前
学习go语言
开发语言·学习·golang
chenzhou__2 小时前
MYSQL学习笔记(个人)(第十五天)
linux·数据库·笔记·学习·mysql
rechol3 小时前
C++ 继承笔记
java·c++·笔记
JJJJ_iii5 小时前
【机器学习01】监督学习、无监督学习、线性回归、代价函数
人工智能·笔记·python·学习·机器学习·jupyter·线性回归
Han.miracle6 小时前
数据结构——二叉树的从前序与中序遍历序列构造二叉树
java·数据结构·学习·算法·leetcode
知识分享小能手7 小时前
uni-app 入门学习教程,从入门到精通,uni-app基础扩展 —— 详细知识点与案例(3)
vue.js·学习·ui·微信小程序·小程序·uni-app·编程
●VON8 小时前
重生之我在大学自学鸿蒙开发第九天-《分布式流转》
学习·华为·云原生·harmonyos·鸿蒙