41.2D动画2DAni反向动力学IK

  1. 41.2D动画-2D骨骼动画-2DAnimation-反向动力学IK
    1. 41.1 知识点
      1. 什么是IK
      2. 2DIK包引入
      3. 2DIK的使用
        1. 给权杖也添加骨骼
        2. 新建一个空物体作为根对象,拖PSB图片做成子物体,给根物体添加IKManager2D组件
        3. IKManager2D脚本参数
        4. 给骨骼的左右手和脚的末端和权杖的末端添加空物体,之后会利用这些空物体在对应位置添加IK点
        5. 在根对象的IKManager2D组件点击加号添加一个Chain(CCD)类型的IK,添加完会出现一个New CCDSolver2D子物体挂载NCCDSolver2D脚本
        6. CCDSolver2D脚本参数
        7. LimbSolver2D脚本参数
        8. 在根对象的IKManager2D组件点击加号添加一个Chain(FABRIK)类型的IK,操作和CCD的完全一样,但是权杖就可以像鞭子一样完全反向了
        9. 在根对象的IKManager2D组件点击加号添加一个Limb类型的IK,关联四肢,这个模式下默认会关联三个骨骼
        10. 创建动画,这时只要修改某个骨骼位置可能就影响多个骨骼了。
        11. 现在IK点不会跟着人物动,而是锁死。想要一起动的话把他放到图片下就行
      4. IK对于我们的意义
    2. 41.2 知识点代码
    3. 41.3 练习题
      1. 请制作一个鼠标指向哪,2D人物的手臂就指向哪里的功能
        1. 创建空物体,拖psb文件图片进来,在左手添加一个空物体
        2. 选择空对象,添加IKManager2D脚本,添加一个IK,选择四肢用的Limb。会创建一个IK位置节点
        3. 在IK位置节点关联左手空物体,点击创建目标按钮,生成IK目标对象
        4. 制作思路:我们可以控制IK目标对象的位置移动手臂,那么只要用鼠标控制IK目标对象就行了
        5. 创建代码挂载到根对象上,定义一个Transform类型的变量,用于存储IK点的位置,在外面关联IK目标对象。需要得到当前2D游戏所在平面的 横截面z轴坐标,用于之后的屏幕坐标转世界坐标,所以Start时使用Camera.main.WorldToScreenPoint方法将IK点的世界坐标转换为屏幕坐标,并获取其z轴值。Update时检测是否按下鼠标左键,按下后得到鼠标位置修改z轴为开始时获得的存储值,使用Camera.main.ScreenToWorldPoint方法将屏幕坐标转换为世界坐标,并赋值给ikPoint变量的position属性,使其移动到鼠标所指向的位置
    4. 41.4 练习题代码

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

×

喜欢就点赞,疼爱就打赏