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

Unity中的数学应用 之 插值函数处理角色朝向 (初中难度 +Matlab)

        CodeMonkey教程: https://www.youtube.com/watch?v=QDWlGOocKm8

        Siki学院汉化教程:如何使用Unity开发分手厨房(胡闹厨房)-Unity2023 - SiKi学院|SiKi学堂 - unity|u3d|虚幻|ue4/5|java|python|人工智能|视频教程|在线课程

版本:Unity6

模板:3D核心(渲染管线:URP)

1.情景

        在3D之中,角色移动朝向处理起来非常简单,因为我们可以获取tranform.forward,也就是当前对象的朝向(在unity之中为左手坐标系,所以对象正朝向为(0,0,1))

        接上一节:Unity中的数学应用 之 角色移动中单位化向量的妙用 (小学难度)-CSDN博客 只需要如下代码即可更改朝向

   if(move!= Vector3.zero) {  
       transform.forward =move;
   }

        但是这样直接赋值给朝向向量会比较生硬

        我们要采用平滑曲线让其有个旋转的过程

2.Vector3.Lerp:线性插值函数

        但不是Mathf.Lerp,因为其是处理单个向量的

        我们需要的是让角色朝向 =>输入朝向(transform.forward =>move)

        unity中的Vector3就有封装好的Lerp   

 transform.forward = Vector3.Lerp(transform.forward, move,Time.deltaTime* roteSpeed);

瞅瞅其背后的公式:

  • ( a ) 是起始向量
  • ( b ) 是结束向量
  • ( t ) 是插值因子,范围在 [0, 1] 之间

还是不直观,我直接用用matlab去绘制一下

% 起始向量和结束向量
a = [0, 0, 0];
b = [10, 10, 10];

% 插值因子 t 的范围
t = linspace(0, 1, 100);

% 计算 Lerp 插值
lerp_x = a(1) + (b(1) - a(1)) * t;
lerp_y = a(2) + (b(2) - a(2)) * t;
lerp_z = a(3) + (b(3) - a(3)) * t;

% 绘制曲线
figure;
plot3(lerp_x, lerp_y, lerp_z, '-o');
xlabel('X');
ylabel('Y');
zlabel('Z');
title('Vector3.Lerp 曲线');
grid on;

       result = start + t * (end - start),这么来看result的线性的

        但是,因为用的是start = start + t * (end - start),而start是复用的不是不变的值,所以就会出现如下的啸问题,我用另外一个例子去直观地描述:

        该脚本挂载在A对象,end代表B对象

    public Transform end;
    private void Update() {
        this.transform.position = Vector3.Lerp(this.transform.position,end.position,0.01f);
    }

        表现为先慢后快,所以在朝向问题上可以选择另外一种插值:球形插值

3.Vector3.SLerp:球形插值函数

        这个公式貌似有点复杂,实际上确实有点复杂

        

请看动画:“四元数的线性插值”与“球面线性插值”的动画理解_哔哩哔哩_bilibili

    其中的角度是向量 a 和 b 之间的角,借用matlab来看其曲线似乎能窥探之一二

% 定义两个初始向量(示例中为二维向量,可类比三维情况)
u = [1, 0]; % 可以理解为方向向量,比如Unity中的某个方向
v = [0, 1]; % 另一个方向向量

% 生成插值参数t的一系列值,这里取多个值来体现曲线变化
t = linspace(0, 1, 100); % 从0到1均匀取100个值用于插值

% 计算向量u和v的夹角的余弦值
cos_omega = dot(u, v) / (norm(u) * norm(v));
% 得到夹角(保证在[0, pi]区间)
omega = acos(cos_omega); 

% 进行Slerp插值
interpolated_vectors = zeros(length(t), 2); % 用于存储插值后的向量
for i = 1:length(t)
    st = sin((1 - t(i)) * omega) / sin(omega);
    tt = sin(t(i) * omega) / sin(omega);
    interpolated_vectors(i, :) = st * u + tt * v;
end

% 绘制曲线,展示插值过程中向量端点的轨迹
plot(interpolated_vectors(:, 1), interpolated_vectors(:, 2));
xlabel('X');
ylabel('Y');
title('Slerp Interpolation Curve');
grid on;

       要是究其根本来讲:四元数存在于四维空间中,Slerp 操作相当于在这个四维超球面上找到两个四元数对应的点,并沿着连接这两点的大圆弧进行插值

        这个大圆弧在四维空间中的性质类似于二维圆上的弧,具有某种意义上的 “均匀性”,确保了插值过程中旋转速度和方向的平稳变化

        要是简单来讲:因为图像中这个圆弧的曲率在各方向(点)上是一致的,当start点向end点移动,是按照这个曲线去“滑行”的,因此就十分平滑且均匀 

实现了以下效果:

 4.总结

        虽然这个问题初中生来了都能解决,但确实是u3d中不可忽视的细节,我将通过线性代数和微积分深挖unity之中一些背后的数学知识

最后,这个视频说不定可以帮助你理解:有关插值的一切_哔哩哔哩_bilibili

        

         


http://www.kler.cn/a/414243.html

相关文章:

  • [Unity] 【游戏开发】角色设计3-如何为角色实现响应输入的控制器
  • 【.net core】【sqlsugar】子查询时的注意事项(持续更新)
  • Linux自动化构建-make/Makefile
  • 14、保存与加载PyTorch训练的模型和超参数
  • Leetcode - 周赛424
  • CTF之密码学(BF与Ook)
  • 【计算机网络】—— 物理层
  • IPguard与Ping32对比评测:数据安全保护谁更强?
  • 【热门主题】000067 React前端框架:探索高效Web开发之路
  • 在C#中使用OpenCV的.net包装器EmguCV
  • 11.25Scala
  • Maven 依赖项配置
  • 初级数据结构——二叉搜索树题库(c++)
  • RHCE——selinux和防火墙
  • 最新特性MCP协议客户端复现
  • 【R安装】VSCODE安装及R语言环境配置
  • 已解决WordPress图片无法显示,免插件实现WordPress上传图片时自动重命名
  • MySQL执行计划explain
  • vmware Ubuntu2004运行STAR-Searcher
  • 结构体详解+代码展示
  • 【Leetcode 每日一题】235. 二叉搜索树的最近公共祖先
  • cocos creator 3.8 合成大西瓜Demo 11
  • 卷积神经网络:图像特征提取与分类的全面指南
  • AIGC时代:如何快速搞定Spring Boot+Vue全栈开发
  • C#基础41-45
  • 栩熙酷科技,抖音电商优势凸显