Unity动画️11. IK动画—手与木头的匹配_unity onanimatorik-程序员宅基地

技术标签: c#  unity  # 动画系统  游戏引擎  

 

 

IK动画与MatchTarget区别:

MatchTarget实现从一段时间区域内,一个点到另一个点匹配的过程;IK动画用于直接将手或脚与某点的匹配

控制策略:a、在木头下新建两个点(空的GameObject),将这两个点调到合适位置,让手与这两个点进行匹配,完成托举木头的效果;

b、在匹配过程中,手部的旋转角度和位置是根据GameObject来匹配的,我们可以通过调节GameObject的角度和位置完成动画的手部角度的调节。

    运行时可暂停运行,调节位置,逐帧更新动画,Transform齿轮处可Copy Component,调节完成后取消运行动画,Paste Component Values

1、勾选动画层的IK Pass

2、Player C#补充:

OnAnimatorIK(int layerIndex)方法在Update()方法外,因为勾选了IK Pass,系统会自动调用

print(layerIndex);可在控制台输出当前调用的动画层是几

Player总代码:

using UnityEngine;

public class Player : MonoBehaviour {

    private Animator anim;
    private int speedRotateID = Animator.StringToHash("SpeedRotate");
    private int speedZID = Animator.StringToHash("SpeedZ");
    private int vaultID = Animator.StringToHash("Vault");
    private Vector3 matchTarget;
    private CharacterController characterController;
    private int vaultCurveID = Animator.StringToHash("vaultCurve");
    private int sliderID = Animator.StringToHash("Slider");
    private int sliderCurveID = Animator.StringToHash("sliderCurve");
    private int isHoldLogID = Animator.StringToHash("IsHoldLog");
    public Transform LeftHand, RightHand;
    public GameObject unityLog;

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

        anim.SetFloat(speedZID, Input.GetAxis("Vertical") * 4.5f);
        anim.SetFloat(speedRotateID, Input.GetAxis("Horizontal")*126);

        ProcessVault();
        ProcessSlider();
    }

    private void ProcessVault()
    {
        if (anim.GetFloat(speedZID) > 3 && anim.GetCurrentAnimatorStateInfo(0).IsName("LocalMotion"))
        {
            RaycastHit hit;
            if (Physics.Raycast(transform.position + Vector3.up * 0.3f, transform.forward, out hit, 4.5f))
            {
                if (hit.collider.tag == "Obstacle")
                {
                    if (hit.distance > 3)
                    {
                        Vector3 point = hit.point;
                        point.y = hit.transform.position.y + hit.collider.bounds.size.y + 0.09f;  //普通的cube在水平面时默认中心高度y=0.5,但此模型水平中心高度为0(和底边一致)!,所以是它最低点位置+Y轴的大小
                        matchTarget = point;

                        anim.SetBool(vaultID, true);
                    }

                }
            }
            else anim.SetBool(vaultID, false);
        }

        characterController.enabled = anim.GetFloat(vaultCurveID) < 0.5f;

        if (anim.GetCurrentAnimatorStateInfo(0).IsName("Vault"))
        {
            anim.MatchTarget(matchTarget, Quaternion.identity, AvatarTarget.LeftHand, new MatchTargetWeightMask(Vector3.one, 0), 0.32f, 0.4f);
        }
    }
    private void ProcessSlider()
    {
        if (anim.GetFloat(speedZID) > 3 && anim.GetCurrentAnimatorStateInfo(0).IsName("LocalMotion"))
        {
            RaycastHit hit;
            if (Physics.Raycast(transform.position + Vector3.up * 1.5f, transform.forward, out hit, 5f))
            {
                if (hit.collider.tag == "Obstacle")
                {
                    if (hit.distance <2.8)
                    {
                        Vector3 point = hit.point;
                        point.y = 0 ; 
                        matchTarget = point+transform.forward*2;
                        anim.SetBool(sliderID, true);
                    }
                }
            }
        }
        else anim.SetBool(sliderID, false);

        if (anim.GetCurrentAnimatorStateInfo(0).IsName("Slider"))
        {
            anim.MatchTarget(matchTarget, Quaternion.identity, AvatarTarget.Root, new MatchTargetWeightMask(new Vector3(1,0,1), 0), 0.38f, 0.67f);
        }

        if (anim.GetCurrentAnimatorStateInfo(0).IsName("Slider" ))
        {
            characterController.enabled = anim.GetFloat(sliderCurveID) < 0.5f;
        }
    }

    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Log")
        {
            Destroy(other.gameObject);
            unityLog.SetActive(true);
            anim.SetBool(isHoldLogID, true);
        }
    }

    private void OnAnimatorIK(int layerIndex)
    {
        if (layerIndex == 1)  //动画层从0开始排序
        {
            //print(layerIndex);
            int Weight = anim.GetBool(isHoldLogID) ? 1 : 0;  //三元运算符
            anim.SetIKPosition(AvatarIKGoal.LeftHand, LeftHand.position);
            anim.SetIKRotation(AvatarIKGoal.LeftHand, LeftHand.rotation);
            anim.SetIKPositionWeight(AvatarIKGoal.LeftHand, Weight);
            anim.SetIKRotationWeight(AvatarIKGoal.LeftHand, Weight);

            anim.SetIKPosition(AvatarIKGoal.RightHand, RightHand.position);
            anim.SetIKRotation(AvatarIKGoal.RightHand, RightHand.rotation);
            anim.SetIKPositionWeight(AvatarIKGoal.RightHand, Weight);
            anim.SetIKRotationWeight(AvatarIKGoal.RightHand, Weight);
        }
    }
}

动画展示:

动画系统其他各功能链接:TimeLine

大家还有什么问题,欢迎在下方留言!


 

在这里插入图片描述


如果你有 技术的问题 或 项目开发

都可以加下方联系方式

和我聊一聊你的故事

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_38239050/article/details/79859384

智能推荐

CRLF学习了解-程序员宅基地

文章浏览阅读1k次。在ASCII中,回车(CR)字符用十进制值13或十六进制值0x0D表示,换行(LF)字符用十进制值10或十六进制值0x0A表示。这两个字符通常一起使用,表示将光标移到下一行的开头位置。CRLF在许多操作系统和编程环境中被广泛使用,例如Windows中的文本文件和网络通信中的协议,如HTTP和SMTP。它们是文本格式化和解析的重要元素。_crlf

python全栈开发—函数再战—实现模块化设计_全栈开发与数学-程序员宅基地

文章浏览阅读256次。函数再战—熟练基础,精通技能,触类旁通之所以又整理了一遍函数,主要是因为当我进行后续学习的时候,发现函数比想象的要NB的多,于是又厚着脸皮又来了一遍,嗯,果然很NB。建议在学习的过程中遇到了难题,记得回头复习复习,也许正是那些你忽略的内容,给未来的你营造出自己是SB的难题。内容概括:函数基本语法及特性函数与局部变量返回值嵌套函数递归匿名函数函数式编程介绍高阶函数内置函数..._全栈开发与数学

在vs开发环境中用opencv读取图片,Debug模式下成功,release模式下失败的可能原因_visual studio的debug模式可以include opencv release模式不行-程序员宅基地

文章浏览阅读921次。1 检查一下release模式下的链接器的输入,其依赖的lib名称最后一个字母是没有"d",d代表debug如图:2 检查一下路径,看是否因为带中文的路径导致编码错误..._visual studio的debug模式可以include opencv release模式不行

教你一步一步使用Excel获取API接口的金融数据_excel的api key-程序员宅基地

文章浏览阅读5.6k次,点赞7次,收藏26次。在用EXCEL做量化分析的时候,经常需要通过一些金融数据平台的API接口,获取各种数据。最常用的公共API接口有Yahoo Finance,Google Finance,新浪财经,搜狐财经等。这些都不需要注册,就可以直接使用。获取方式相对简单,但数据种类不够丰富,通常只包括交易数据和财务数据。另外一些免费的金融数据平台,如国外的Quandl和国内的Tushare也都提供了API接口,数据种类更..._excel的api key

ThinkPHP去除url中的index.php,绝对管用!-程序员宅基地

文章浏览阅读1.6k次。例如你的原路径是 http://localhost/test/index.php/index/add那么现在的地址是 http://localhost/test/index/add如何去掉index.php呢?1.httpd.conf配置文件中加载了mod_rewrite.so模块 //在APACHE里面去配置#LoadModule rewrite_module modu

Qt核心机制与原理_qt原理-程序员宅基地

文章浏览阅读3.8k次,点赞5次,收藏39次。★了解Qt和C++的关系★掌握Qt的信号/槽机制的原理和使用方法★了解Qt的元对象系统★掌握Qt的架构★理解Qt的事件模型,掌握其使用的时机信号与槽、元对象系统、事件模型是Qt机制的核心,如果您想要掌握Qt编程,就需要对它们有比较深入的了解。本章重点介绍了信号与槽的基本概念和用法、元对象系统、Qt的事件模型,以及它们在实际使用过程中应注意的一些问题。Qt对标准C++的扩展标准C++对象模型为面向对象编程提供了有效的实时支持,但是它的静态特性在一些领域中表现的不够灵活。事实上,GUI应用程序_qt原理

随便推点

Crank Storyboard Suite入门(一)_crank_storyboard_suite-v5.3.0-程序员宅基地

文章浏览阅读3.5k次,点赞4次,收藏5次。Crank Storyboard Suite是一个十分容易学习的用来设计嵌入式界面的软件,软件可以导出为Android上可执行的apk文件。下面从最简单的例子开始,建立一个如下所示的界面,上面的图标有按下的效果。1)选择File->New->Storyboard Application新近一个工程。2. 在工程里面的文件夹里_crank_storyboard_suite-v5.3.0

爬虫框架 - feapder_feapder 网盘-程序员宅基地

文章浏览阅读1.0k次。1. 前言众所周知,Python 最流行的爬虫框架是 Scrapy,它主要用于爬取网站结构性数据今天推荐一款更加简单、轻量级,且功能强大的爬虫框架:feapder项目地址:https://github.com/Boris-code/feapder2. 介绍及安装和 Scrapy 类似,feapder 支持轻量级爬虫、分布式爬虫、批次爬虫、爬虫报警机制等功能内置的 3 种爬虫如下: AirSpider 轻量级爬虫,适合简单场景、数据量少的爬虫 Spider._feapder 网盘

《数据结构与算法分析:Java语言描述》.pdf-程序员宅基地

文章浏览阅读6k次,点赞2次,收藏6次。关注“Java后端技术全栈”回复“面试”获取全套大厂面试资料程序=数据结构+算法这好比是软件工程师的“武林秘籍”。数据结构指的是数据与数据之间的逻辑关系;算法指的是解决特定问题的步骤和方..._数据结构与算法分析java语言描述pdf

PyTorch——自注意力(self-attention)机制实现(代码详解)_自注意力机制代码-程序员宅基地

文章浏览阅读8w次,点赞111次,收藏691次。参考链接https://www.bilibili.com/video/BV1JE411g7XF?p=54https://arxiv.org/abs/1706.03762https://blog.csdn.net/qq_36653505/article/details/83375160简述自注意力机制(self-attention)self-attention可以视为一个特征提取层,给定输入特征a1,a2,⋅⋅⋅ana^{1},a^{2},\cdot \cdot \cdot a^{n}a1,a2_自注意力机制代码

在Vue中应用cornerstone并且实时更新缩放比例等数据_浏览器缩放倍数变化时 更新数据 vue-程序员宅基地

文章浏览阅读1.6k次。在Vue中应用cornerstone并且跟随dicom实时更新缩放比例等数据最近需要在cornerstone的显示界面中显示一些数据,比如缩放比例以及渲染时间等,但是这些是需要根据鼠标事件进行实时更新的,想想肯定是有这个接口的,于是便试了一下。1、获取到当前视窗的对象获取到视窗这个对象因为它里面肯定会有许多属性可以直接被使用,刚好我们的缩放比例就是里面的scale,还有一些属性可以直接取用。..._浏览器缩放倍数变化时 更新数据 vue

C语言中常用的函数_c语言常用函数-程序员宅基地

文章浏览阅读3.1w次,点赞135次,收藏1k次。C语言中常用的函数1、putchar()函数2、getchar()函数3、pow( a , b )函数4、sqrt( a )函数5、fabs(a)函数6、puts(字符数组)函数——输出字符串的函数7、gets(字符数组)——输入字符串的函数8、strcat(a , b)函数——字符串连接函数9、strcpy函数——字符串复制函数10、strncpy函数——字符串复制函数11、strcmp函数——字符串比较函数12、strlen函数——测量字符串长度的函数13、strlwr函数——转换为小写的函数14、_c语言常用函数

推荐文章

热门文章

相关标签