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
}
相关推荐
Engineer邓祥浩13 小时前
宏观认知(1):AI 是什么——吴恩达《AI for Everyone》Week1 学习笔记
人工智能·笔记·学习
暴躁小师兄数据学院13 小时前
【AI大模型应用开发工程师特训笔记】第04讲(第五章):条件判断与流程控制
大数据·人工智能·python·学习
我是一只码蚁13 小时前
记一次苍穹外卖项目 Maven 编译报错的排查与解决全过程
java·经验分享·笔记·后端·架构·maven
3DVisionary14 小时前
混凝土裂纹如何全自动识别?DIC技术在结构裂缝重构的应用
人工智能·学习·dic技术·混凝土裂缝监测·全场应变分析·三维位移测量·实验力学
鹏北海-RemHusband14 小时前
Go 语言基础笔记 — 面向 JS/TS 前端开发者
笔记·golang
魔法阵维护师14 小时前
从零开发游戏需要学习的c#模块,第二十八章(血条显示 —— 敌人与玩家生命可视化)
学习·游戏·c#
sheeta199814 小时前
LeetCode 每日一题笔记 日期:2026.05.28 题目:3093. 最长公共后缀查询
linux·笔记·leetcode
墨白曦煜14 小时前
算法实战笔记:链表的底层逻辑与指针的高阶玩法(二)
笔记·算法·链表
AOwhisky15 小时前
Ceph系列第一期:Ceph分布式存储核心概念与架构初识
linux·运维·笔记·分布式·ceph·学习·架构
Bechamz15 小时前
大数据开发学习Day44
大数据·学习