41.2D动画-2D骨骼动画-2DAnimation-反向动力学IK
41.1 知识点
什么是IK
- 在骨骼动画中,构建骨骼的方法被称为正向动力学。
- 它的表现形式是,子骨骼(关节)的位置根据父骨骼(关节)的旋转而改变。
- 用我们人体举例子,当我们抬起手臂时,是肩部关节带动的整个手臂的运动,用父子骨骼理解的话就是父带动了子。
- 而IK全称是Inverse Kinematics,翻译过来的意思就是反向动力学的意思。
- 它和正向动力学恰恰相反。
- 它的表现形式是,子骨骼(关节)末端的位置改变会带动自己以及自己的父骨骼(关节)旋转。
- 用我们人体举例子,当我们拿起一个杯子的时候是用手掌去拿,以杯子为参照物,我们移动杯子的位置,手臂会随着杯子一起移动,用父子骨骼理解的话就是子带动了父。
2DIK包引入
- 在Package Manager窗口中引入2D IK工具包,需要在Advanced高级选项中选中Show preview packages(显示预览包),这样才能看到2D IK相关内容。
- 注意:如果在引入包时报错,需要在Windows防火墙中添加入站规则。
- 解决引入包报错
- 开始菜单点击设置。
- 搜索防火墙,打开Window Defender防火墙选项。
- 点击高级设置。
- 左边点击入站规则。
- 右边点击新建规则。
- 弹出的窗口选择程序,下一步。
- 选择程序的路径,选择Unity桌面快捷方式就行了,下一步。
- 选择允许连接,下一步。
- 域 专用 公用 都勾选,下一步。
- 名称取名Unity,完成。
- 2D项目可能也不会自动下载,除非Unity版本很高可能会自动下载。
2DIK的使用
给权杖也添加骨骼
新建一个空物体作为根对象,拖PSB图片做成子物体,给根物体添加IKManager2D组件
IKManager2D脚本参数
- IK Solvers:IK解算器,在这里添加IK。
- Chain(CCD):可以自定义影响N个关节点,不能反向。
- Chain(FABRIK):可以自定义影响N个关节点,可以反向。
- Limb:只会影响3个关节点。
- Weight:权重,当有多个IK控制同一点时权重会影响控制的百分比。
- Restore Default Pose:回复默认位置。
给骨骼的左右手和脚的末端和权杖的末端添加空物体,之后会利用这些空物体在对应位置添加IK点
在根对象的IKManager2D组件点击加号添加一个Chain(CCD)类型的IK,添加完会出现一个New CCDSolver2D子物体挂载NCCDSolver2D脚本
CCDSolver2D脚本参数
- Effector:确定IK的默认位置
- 比如可以把权杖末端的空对象赋值进来。
- Chain Length:IK影响的骨骼数量,往上影响多少个骨骼节点,加大数值,点变成绿色就意味着影响了那个骨骼。
- Iterations:算法运行的次数。
- Tolerance:容错程度。
- Velocity:速度。
- 点击创建对象,会出来一个对象并关联,这个对象可以理解为创建出来的IK节点,通过这个IK节点反向控制骨骼,现在移动子物体因为有了IK父物体也会跟着动。
- CCD模式不能完全反向。
LimbSolver2D脚本参数
- Effector:默认的IK点位置。
- Target:会根据IK点位置生成真正的IK点对象。
- Flip:反向。
- Constrain Rotation:约束旋转程度。
- Solve from Default Pose:从默认姿势进行求解计算。
- Weight:权重。
- Create Target:创建IK节点。
- Restore Default Pose:重置默认形状。
在根对象的IKManager2D组件点击加号添加一个Chain(FABRIK)类型的IK,操作和CCD的完全一样,但是权杖就可以像鞭子一样完全反向了
在根对象的IKManager2D组件点击加号添加一个Limb类型的IK,关联四肢,这个模式下默认会关联三个骨骼
创建动画,这时只要修改某个骨骼位置可能就影响多个骨骼了。
现在IK点不会跟着人物动,而是锁死。想要一起动的话把他放到图片下就行
IK对于我们的意义
- 瞄准功能。
- 头部朝向功能。
- 拾取物品功能等等有指向性的功能时,我们都可以通过IK来达到目的。
- 最大的作用,可以方便我们进行动画制作。
41.2 知识点代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson41_2D动画_2D骨骼动画_2DAnimation_反向动力学IK : MonoBehaviour
{
void Start()
{
#region 知识点一 什么是IK?
//在骨骼动画中,构建骨骼的方法被称为正向动力学
//它的表现形式是,子骨骼(关节)的位置根据父骨骼(关节)的旋转而改变
//用我们人体举例子
//当我们抬起手臂时,是肩部关节带动的整个手臂的运动,用父子骨骼理解的话就是父带动了子
//而IK全称是Inverse Kinematics,翻译过来的意思就是反向动力学的意思
//它和正向动力学恰恰相反
//它的表现形式是,子骨骼(关节)末端的位置改变会带动自己以及自己的父骨骼(关节)旋转
//用我们人体举例子
//当我们拿起一个杯子的时候是用手掌去拿,以杯子为参照物,我们移动杯子的位置,手臂会随着杯子一起移动
//用父子骨骼理解的话就是子带动了父
#endregion
#region 知识点二 2DIK包引入
//在Package Manager窗口中引入2D IK工具包
//需要在Advanced高级选项中选中Show preview packages(显示预览包)
//这样才能看到2D IK相关内容
//注意:如果在引入包时报错,需要在Windows防火墙中添加入站规则
#endregion
#region 知识点三 2DIK的使用
#endregion
#region 知识点四 IK对于我们的意义
//1.瞄准功能
//2.头部朝向功能
//3.拾取物品功能
//等等有指向性的功能时 我们都可以通过IK来达到目的
//最大的作用,可以方便我们进行动画制作
#endregion
}
}
41.3 练习题
请制作一个鼠标指向哪,2D人物的手臂就指向哪里的功能
创建空物体,拖psb文件图片进来,在左手添加一个空物体
选择空对象,添加IKManager2D脚本,添加一个IK,选择四肢用的Limb。会创建一个IK位置节点
在IK位置节点关联左手空物体,点击创建目标按钮,生成IK目标对象
制作思路:我们可以控制IK目标对象的位置移动手臂,那么只要用鼠标控制IK目标对象就行了
创建代码挂载到根对象上,定义一个Transform类型的变量,用于存储IK点的位置,在外面关联IK目标对象。需要得到当前2D游戏所在平面的 横截面z轴坐标,用于之后的屏幕坐标转世界坐标,所以Start时使用Camera.main.WorldToScreenPoint方法将IK点的世界坐标转换为屏幕坐标,并获取其z轴值。Update时检测是否按下鼠标左键,按下后得到鼠标位置修改z轴为开始时获得的存储值,使用Camera.main.ScreenToWorldPoint方法将屏幕坐标转换为世界坐标,并赋值给ikPoint变量的position属性,使其移动到鼠标所指向的位置
public Transform ikPoint; //定义一个Transform类型的变量,用于存储IK点的位置
private float z; //定义一个float类型的变量,用于存储当前2D游戏所在平面的z轴坐标
private Vector3 mousePos; //定义一个Vector3类型的变量,用于存储鼠标的位置
void Start()
{
//这里是为了得到当前2D游戏所在平面的 横截面z轴坐标 用于之后的 屏幕坐标转世界坐标
z = Camera.main.WorldToScreenPoint(ikPoint.position).z; //使用Camera.main.WorldToScreenPoint方法将IK点的世界坐标转换为屏幕坐标,并获取其z轴值
}
void Update()
{
print(Camera.main.WorldToScreenPoint(this.transform.position).z); //打印当前物体的屏幕坐标的z轴值,用于调试
if (Input.GetMouseButton(0)) //判断是否按下鼠标左键
{
//得到当前鼠标所在位置
mousePos = Input.mousePosition; //使用Input.mousePosition属性获取鼠标的屏幕坐标,并赋值给mousePos变量
//改变z轴 为了之后转换世界坐标后 横截面位置的正确
mousePos.z = z; //将mousePos变量的z轴值修改为之前获取的z变量的值,保证屏幕坐标和世界坐标在同一平面上
ikPoint.position = Camera.main.ScreenToWorldPoint(mousePos); //使用Camera.main.ScreenToWorldPoint方法将mousePos变量的屏幕坐标转换为世界坐标,并赋值给ikPoint变量的position属性,使其移动到鼠标所指向的位置
}
}
41.4 练习题代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Experimental.U2D.IK;
public class Lesson41_练习题 : MonoBehaviour
{
#region 练习题一
//请制作一个鼠标指向哪,2D人物的手臂就指向哪里的功能
public Transform ikPoint; //定义一个Transform类型的变量,用于存储IK点的位置
private float z; //定义一个float类型的变量,用于存储当前2D游戏所在平面的z轴坐标
private Vector3 mousePos; //定义一个Vector3类型的变量,用于存储鼠标的位置
void Start()
{
//这里是为了得到当前2D游戏所在平面的 横截面z轴坐标 用于之后的 屏幕坐标转世界坐标
z = Camera.main.WorldToScreenPoint(ikPoint.position).z; //使用Camera.main.WorldToScreenPoint方法将IK点的世界坐标转换为屏幕坐标,并获取其z轴值
}
void Update()
{
print(Camera.main.WorldToScreenPoint(this.transform.position).z); //打印当前物体的屏幕坐标的z轴值,用于调试
if (Input.GetMouseButton(0)) //判断是否按下鼠标左键
{
//得到当前鼠标所在位置
mousePos = Input.mousePosition; //使用Input.mousePosition属性获取鼠标的屏幕坐标,并赋值给mousePos变量
//改变z轴 为了之后转换世界坐标后 横截面位置的正确
mousePos.z = z; //将mousePos变量的z轴值修改为之前获取的z变量的值,保证屏幕坐标和世界坐标在同一平面上
ikPoint.position = Camera.main.ScreenToWorldPoint(mousePos); //使用Camera.main.ScreenToWorldPoint方法将mousePos变量的屏幕坐标转换为世界坐标,并赋值给ikPoint变量的position属性,使其移动到鼠标所指向的位置
}
}
#endregion
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com