当前位置: 首页 > news >正文

Unity Avatar Foot IK - Avatar Foot Placement Resolution

文章目录

  • 简介
  • 实现
    • Avatar FBX Import Settings
    • Animator Settings
    • On Animator IK
    • Calculate IK Position & Rotation
    • Body Position
    • Apply IK Position & Rotation


简介

通过Unity内部的Mecanim动画系统实现的FootIK功能,效果如图所示,左右分别为开启和关闭FootIK的效果:

效果图(一)

效果图(二)

效果图(三)

效果图(四)

初版1.0.0代码已上传至SKFramework框架PackageManager中:

SKFramework PackageManager

相关变量说明:

Avatar Foot IK

  • Enable Foot Ik:是否启用FootIK
  • Foot Ik Pass Layer Index:Animator启用IKPass对应的层级
  • Layer Mask:射线检测时所有的层级
  • Body Y Offset:身体Y坐标的偏移量
  • Body Position Lerp Speed:身体坐标插值的速度
  • Foot Position Lerp Speed:脚部坐标插值的速度
  • Raycast Distance:射线检测的最大距离
  • Raycast Origin Height:射线检测的高度

实现

Avatar FBX Import Settings

  • Animation Type: 需要Humanoid人形动画

Animation Type

  • Avatar Configuration:确保配置正确

Avatar Configuration

Animator Settings

  • Foot IK:相应的Animator State中需要开启Foot IK

Foot IK

  • IK Pass:相应的Animator Layer中需要开启IK Pass通道

IK Pass

On Animator IK

动画IK回调函数,Unity Documentation中这样介绍:OnAnimatorIK() 在即将更新其内部反向动力学系统前由动画器组件调用。该回调可用于设置反向动力学目标的位置及其各自的权重。

参数LayerIndex指的是Animator中的Layer层级的索引值。

OnAnimatorIK
如何设置IK目标的位置及其权重?需要用到Animator中的函数:

  • SetIKPosition:设置一个IK Goal的位置
  • SetIKPositionWeight:设置IK Goal的过渡权重(0表示IK之前的原始动画,1表示在goal)
  • SetIKRotation:设置一个IK Goal的旋转
  • SetIKRotationWeight:设置IK Goal的旋转权重

Calculate IK Position & Rotation

如何获取IK目标位置及旋转?可以通过在脚部加上一定单位的高度上向下进行Raycast射线检测,RaycastHit中的point碰撞点即是IK的目标位置,并且通过normal法线方向获得IK的目标旋转,代码如下所示:

#region 计算左脚IK
//左脚坐标
leftFootPosition = animator.GetBoneTransform(HumanBodyBones.LeftFoot).position;
leftFootPosition.y = transform.position.y + raycastOriginHeight;//左脚 射线检测
leftFootRaycast = Physics.Raycast(leftFootPosition, Vector3.down, out RaycastHit hit, raycastDistance + raycastOriginHeight, layerMask);
if (leftFootRaycast)
{leftFootIkPosition = leftFootPosition;leftFootIkPosition.y = hit.point.y + bodyYOffset;leftFootIkRotation = Quaternion.FromToRotation(transform.up, hit.normal);
#if UNITY_EDITOR//射线Debug.DrawLine(leftFootPosition, leftFootPosition + Vector3.down * (raycastDistance + raycastOriginHeight), Color.yellow);//法线Debug.DrawLine(hit.point, hit.point + hit.normal * .5f, Color.cyan);
#endif
}
else
{leftFootIkPosition = Vector3.zero;
}
#endregion

Body Position

在设置IK目标位置之前,需要先计算和调整身体的高度,原因如下图所示,当射线检测到的IK Position,腿的长度达不到时,需要将身体的Y坐标减去相应距离。

身体高度通过Animator中的bodyPosition去调整:

Animator bodyPosition

代码如下所示:

#region 身体
if (leftFootRaycast && rightFootRaycast)
{//左脚坐标Y差值float leftPosYDelta = leftFootIkPosition.y - transform.position.y;//右脚坐标Y差值float rightPosYDelta = rightFootIkPosition.y - transform.position.y;//身体坐标Y差值取二者最小值float bodyPosYDelta = Mathf.Min(leftPosYDelta, rightPosYDelta);//目标身体坐标Vector3 targetBodyPosition = animator.bodyPosition + Vector3.up * bodyPosYDelta;//插值运算targetBodyPosition.y = Mathf.Lerp(lastBodyPositionY, targetBodyPosition.y, bodyPositionLerpSpeed);//设置身体坐标animator.bodyPosition = targetBodyPosition;
}
//缓存身体Y坐标
lastBodyPositionY = animator.bodyPosition.y;
#endregion

Apply IK Position & Rotation

求得目标位置和旋转并调整完身体高度后,应用目标位置和旋转即可:

#region 应用左脚IK
//权重
animator.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 1f);
animator.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 1f);Vector3 targetIkPosition = animator.GetIKPosition(AvatarIKGoal.LeftFoot);
if (leftFootRaycast)
{//转局部坐标targetIkPosition = transform.InverseTransformPoint(targetIkPosition);Vector3 world2Local = transform.InverseTransformPoint(leftFootIkPosition);//插值计算float y = Mathf.Lerp(lastLeftFootPositionY, world2Local.y, footPositionLerpSpeed);targetIkPosition.y += y;lastLeftFootPositionY = y;//转全局坐标targetIkPosition = transform.TransformPoint(targetIkPosition);//当前旋转Quaternion currRotation = animator.GetIKRotation(AvatarIKGoal.LeftFoot);//目标旋转Quaternion nextRotation = leftFootIkRotation * currRotation;animator.SetIKRotation(AvatarIKGoal.LeftFoot, nextRotation);
}
animator.SetIKPosition(AvatarIKGoal.LeftFoot, targetIkPosition);
#endregion

相关文章:

Unity Avatar Foot IK - Avatar Foot Placement Resolution

文章目录简介实现Avatar FBX Import SettingsAnimator SettingsOn Animator IKCalculate IK Position & RotationBody PositionApply IK Position & Rotation简介 通过Unity内部的Mecanim动画系统实现的FootIK功能,效果如图所示,左右分别为开启…...

是时候告别这些 Python 库了

随着每个 Python 版本的发布,都会添加新模块,并引入新的更好的做事方式,虽然我们都习惯了使用好的旧 Python 库和某些做事方式,但现在也时候升级并利用新的和改进的模块及其特性了。 文章目录技术提升PathlibSecretsZoneinfoDatac…...

nodejs基于vue论坛交流管理系统

可定制框架:ssm/Springboot/vue/python/PHP/小程序/安卓均可开发目录 目录 1 绪论 1 1.1课题背景 1 1.2课题研究现状 1 1.3初步设计方法与实施方案 2 1.4本文研究内容 2 2 系统开发环境 4 3 系统分析 6 3.1系统可行性分析 6 3.1.1经济可行性 6 3.1.2技术可行性 6 3.1.3运行可行…...

企业电子招投标采购系统源码之系统的首页设计

​​ 功能模块: 待办消息,招标公告,中标公告,信息发布 描述: 全过程数字化采购管理,打造从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理。通供应商门户具备内外协同的能力,为…...

华为OD机试真题Python实现【竖直四子棋】真题+解题思路+代码(20222023)

竖直四子棋 题目 竖直四子棋的棋盘是竖立起来的,双方轮流选择棋盘的一列下子, 棋子因重力落到棋盘底部或者其他棋子之上,当一列的棋子放满时,无法再在这列上下子。 一方的4个棋子横、竖或者斜方向连成一线时获胜。 现给定一个棋盘和红蓝对弈双方的下子步骤,判断红方或蓝…...

LeetCode 73. 矩阵置零

LeetCode 73. 矩阵置零 难度:middle\color{orange}{middle}middle 题目描述 给定一个 KaTeX parse error: Double subscript at position 3: _m_̲ x _n_ 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法…...

「TCG 规范解读」第10章 TPM工作组 保护你的数字环境

可信计算组织(Ttrusted Computing Group,TCG)是一个非盈利的工业标准组织,它的宗旨是加强在相异计算机平台上的计算环境的安全性。TCG于2003年春成立,并采纳了由可信计算平台联盟(the Trusted Computing Platform Alli…...

华为OD机试真题Python实现【 找字符】真题+解题思路+代码(20222023)

找字符 题目 给定两个字符串, 从字符串2中找出字符串1中的所有字符, 去重并按照 ASCII 码值从小到大排列。 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD机试(Python)真题目录汇总 ## 输入 字符范围满足 ASCII 编码要求, 输入字符串1长度不超过1024, 字符串…...

如何解决多继承下的 菱形继承 问题

目录 概念: 菱形虚拟继承: 概念: 此时D类属于多继承,可以看到D类里面会有两份A类的数据,菱形继承也并不一定就一定就是上图的菱形,假如B类下面还有一个类,D类继承它,同样也是菱形继承问题 cla…...

rk3288-android8.1-以太网ethernet和蓝牙Bluetooth

遇到一个现象,以太网和蓝牙打不开 经过不断分析和查找发现问题在.config中 CONFIG_MOTORCOMM_PHYy 会导致以太网的eth0注册不成功(现在是双网口,还有个USB网卡) 改成# CONFIG_MOTORCOMM_PHY is not set 后以太网可以正常 # CONFIG_RTC_DRV_RK808 is not set 会导致蓝牙打不…...

算法比赛——必备的数论知识

秋名山码民的主页 🎉欢迎关注🔎点赞👍收藏⭐️留言📝 🙏作者水平有限,如发现错误,还请私信或者评论区留言! 目录一、欧几里得二、扩展欧几里得三、算术基本定理四、线性筛选求质数五…...

Docker概述

什么是Docker我们要学习在Linux(RockyLinux)中安装使用Docker来配置软件的功能Docker是一个用来开发、运输和运行应用程序的开放平台。使用Docker可以将应用程序与基础结构分离,以便快速交付软件。使用Docker,您可以以管理应用程序的方式管理基础架构。通…...

实验室设计建设方案主要内容

实验室设计建设整体解决方案SICOLAB需要综合考虑实验室的功能需求、空间布局、设备选型、安全防护、节能环保等多方面因素。以下是一个基本的实验室设计建设方案的流程:一、需求分析:了解实验室的使用目的、实验内容、使用人数、设备种类、实验标准等&am…...

华为OD机试真题Python实现【日志采集系统】真题+解题思路+代码(20222023)

日志采集系统 题目 日志采集是运维系统的的核心组件。日志是按行生成,每行记做一条,由采集系统分批上报。 如果上报太频繁,会对服务端造成压力; 如果上报太晚,会降低用户的体验; 如果一次上报的条数太多,会导致超时失败。 为此,项目组设计了如下的上报策略: 每成功上…...

Python的模块与工具包

模块 模块是一个Python文件,以 .py结尾。模块能定义函数,类和变量,模块里也能包含可执行的代码。 作用 python 中有很多各种不同的模块,每一个模块都可以帮助我们快速的实现一些功能,比如实现和时间相关的功能就可以…...

联合熵和条件熵

本专栏包含信息论与编码的核心知识,按知识点组织,可作为教学或学习的参考。markdown版本已归档至【Github仓库:information-theory】,需要的朋友们自取。或者公众号【AIShareLab】回复 信息论 也可获取。 文章目录联合熵条件熵联合…...

华为OD机试真题Python实现【求最大数字】真题+解题思路+代码(20222023)

求最大数字 题目 给定一个由纯数字组成以字符串表示的数值,现要求字符串中的每个数字最多只能出现2次,超过的需要进行删除;删除某个重复的数字后,其它数字相对位置保持不变。 如34533,数字3重复超过2次,需要删除其中一个3,删除第一个3后获得最大数值4533 请返回经过删…...

Python爬虫(10)selenium爬虫后数据,存入csv、txt并将存入数据并对数据进行查询

之前的文章有关于更多操作方式详细解答,本篇基于前面的知识点进行操作,如果不了解可以先看之前的文章 Python爬虫(1)一次性搞定Selenium(新版)8种find_element元素定位方式 Python爬虫(2)-Selenium控制浏览…...

Python 之 Pandas 时间函数 time 、datetime 模块和时间处理基础

文章目录一、time 模块1、时间格式转换图2. struct_time 元组元素结构3. format time 结构化表示二、datetime 模块1. date类2. 方法和属性3. datetime 类三、timedelta 类的时间加减四、时间处理基础Python 中提供了对时间日期的多种多样的处理方式,主要是在 time …...

C语言学习及复习笔记-【5】C 运算符

文章目录5. C 运算符5.1 关系运算符5.2 逻辑运算符5.3 位运算符5.4 杂项运算符 ↦ sizeof & 三元5.5 例子1). 利用异或 ^ 来交换两个数的值,而且不引入其他变量。2). 利用位与 & 运算,判断一个整数是否是2的整数次幂。3). 不同长度的数据进行位运…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]

报错信息&#xff1a;libc.so.6: cannot open shared object file: No such file or directory&#xff1a; #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...

MySQL体系架构解析(三):MySQL目录与启动配置全解析

MySQL中的目录和文件 bin目录 在 MySQL 的安装目录下有一个特别重要的 bin 目录&#xff0c;这个目录下存放着许多可执行文件。与其他系统的可执行文件类似&#xff0c;这些可执行文件都是与服务器和客户端程序相关的。 启动MySQL服务器程序 在 UNIX 系统中&#xff0c;用…...

基于 HTTP 的单向流式通信协议SSE详解

SSE&#xff08;Server-Sent Events&#xff09;详解 &#x1f9e0; 什么是 SSE&#xff1f; SSE&#xff08;Server-Sent Events&#xff09; 是 HTML5 标准中定义的一种通信机制&#xff0c;它允许服务器主动将事件推送给客户端&#xff08;浏览器&#xff09;。与传统的 H…...

PCA笔记

✅ 问题本质&#xff1a;为什么让矩阵 TT 的行列式为 1&#xff1f; 这个问题通常出现在我们对数据做**线性变换&#xff08;旋转/缩放&#xff09;**的时候&#xff0c;比如在 PCA 中把数据从原始坐标系变换到主成分方向时。 &#x1f4cc; 回顾一下背景 在 PCA 中&#xff…...

android计算器代码

本次作业要求实现一个计算器应用的基础框架。以下是布局文件的核心代码&#xff1a; <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"andr…...

大语言模型解析

1. Input Embedding embedding&#xff1a;将自然语言翻译成index 每个index对应一个embedding&#xff0c;embedding需要训练&#xff0c;embedding是一个数组...