草庐IT

【Unity】Unity 几何知识、弧度、三角函数、向量运算、点乘、叉乘

是嘟嘟啊 2024-01-04 原文

文章目录


基础几何知识

角的度量方式

角的度量方式分为角度(Degree)和弧度(Radian)两种。角度就是将一个圆形切成360份,每一份就是1度角。弧度是当弧长等于圆的半径时即为1弧度。

如图所示:

角度弧度转换

常用换算:
  π = 180 度 \ \pi = 180度  π=180
  1 弧 度 = 180 度 / π \ 1弧度 = 180度 / \pi  1=180/π
  1 角 度 = π / 180 度 \ 1角度 = \pi / 180度  1=π/180

角度转弧度:

  • 转换公式:   弧 度 = 角 度 数 ∗ π / 180 \ 弧度 = 角度数 * \pi / 180  =π/180
  • Unity代码:radian = x * Mathf.Deg2Rad;

弧度转角度:

  • 转换公式:   角 度 = 弧 度 数 ∗ 180 / π \ 角度 = 弧度数 * 180 / \pi  =180/π
  • Unity代码:degree = x * Mathf.Rad2Deg;

三角函数

在直角三角形中(下图为例),如果   a 、 b 、 c 、 x \ a、b、c、x  abcx中的两个变量已知则能计算出另外两个变量的值。

计算公式

正弦   s i n ( x ) = a / c \ sin(x) = a / c  sin(x)=a/c (对比斜)
余弦   c o s ( x ) = b / c \ cos(x) = b / c  cos(x)=b/c (临比斜)
正切   t a n ( x ) = a / b \ tan(x) = a / b  tan(x)=a/b (对比临)
余切   c o t ( x ) = b / a \ cot(x) = b / a  cot(x)=b/a
正割   s e c ( x ) = c / b \ sec(x) = c / b  sec(x)=c/b
余割   c s c ( x ) = c / a \ csc(x) = c / a  csc(x)=c/a
反正弦   a r c s i n ( a / c ) = x \ arcsin(a / c) = x  arcsin(a/c)=x
反余弦   a r c c o s ( b / c ) = x \ arccos(b / c) = x  arccos(b/c)=x
反正切   a r c t a n ( a / b ) = x \ arctan(a / b) = x  arctan(a/b)=x

已知一角和一边,求另外两边,用sin、cos、tan。
已知两边,求角,用arcsin、arccos、arctan。

常用三角函数值

使用方法

已知一个角和一条边,用   s i n 、 c o s 、 t a n \ sin、cos、tan  sincostan
已知两条边求角度,用   A r c S i n 、 A r c C o s 、 A r c T a n \ ArcSin、ArcCos、ArcTan  ArcSinArcCosArcTan

Unity应用

在代码中调用Mathf.Sin等三角函数方法时传入的参数并不是角度,而是弧度。

比如如果我们想要获取sin30度的值不能这样写:Mathf.Sin(30)。这样是错的
正确的写法应该是Mathf.Sin(30 * Mathf.Deg2Rad),将角度转为弧度再传参,得到的结果就是0.5了。

下图为官方API的描述。

要求输入的角度是以弧度为单位的,所以要用这些方法时经常要用到角度和弧度的转换。

向量

向量是一个数字列表,表示各个维度上的有向位移。它是一个有大小有方向的物理量。大小就是方向的模长,方向描述了空间中向量的指向。向量可以用来表示物体的位置和方向。

向量的大小:也就是向量的长度(一般称作为 模),向量a的模记为   ∣ a ⃗ ∣ \ | \vec a |  a ,若   a ⃗ = ( x , y , z ) \ \vec a = (x, y, z)  a =(x,y,z)   ∣ a ⃗ ∣ = x 2 + y 2 + z 2 \ | \vec a | = \sqrt {x^2 + y^2 + z^2}  a =x2+y2+z2 。代码中使用myVector.magnitude来获取向量的大小。

单位向量:即模为1的向量,在Unity中单位向量也就代表了向量的方向。可以记作 a ^ \widehat{a} a 。一个向量的单位向量,可以通过除以它模得到,即 a ^ = a ⃗ ∣ a ⃗ ∣ \widehat{a} = \frac {\vec a} {| \vec a |} a =a a 。代码中使用myVector.normalized来获取向量的单位向量,也就是向量的方向。

零向量:即模为0的向量,零向量的方向是任意的。

相反向量:长度相等方向相反的向量,   a ⃗ \ \vec a  a 的相反向量为   − a ⃗ \ -\vec a  a

平行(共线)向量:方向相同或相反的非零向量,记作   a ⃗ / / b ⃗ \ \vec a // \vec b  a //b

向量加减法

向量的加减就是向量对应分量的加减,类似于物理学中力的正交分解。

向量相减

向量相减等于各分量相减。

  [ x 1 , y 1 , z 1 ] − [ x 2 , y 2 , z 2 ] = [ x 1 − x 2 , y 1 − y 2 , z 1 − z 2 ] \ [x1,y1,z1] - [x2,y2,z2] = [x1-x2 , y1-y2 , z1-z2]  [x1,y1,z1][x2,y2,z2]=[x1x2,y1y2,z1z2]

几何意义:向量a与向量b相减,结果理解为以b的终点为起点,以a的终点为终点的向量。方向由b指向a。
注意:我们可以把向量相减理解为a、b终点的连接,但实际上该向量准确起始位置应该是坐标原点。

实际应用:计算两点之间的距离和相对方向。

向量相加

向量相加等于各分量相加。

  [ x 1 , y 1 , z 1 ] + [ x 2 , y 2 , z 2 ] = [ x 1 + x 2 , y 1 + y 2 , z 1 + z 2 ] \ [x1,y1,z1] + [x2,y2,z2] = [x1+x2 , y1+y2 , z1+z2]  [x1,y1,z1]+[x2,y2,z2]=[x1+x2,y1+y2,z1+z2]

几何意义:如下图,假设空间中有两个向量a和b,a与a’平行且长度相等,b与b’平行且长度相等。a+b就相当于a,b,a’,b’所围成的平行四边形的对角线。

也可以这么说,由向量a的起点出发,沿着a的方向走a的长度,然后沿着b的方向走b的长度,达到的点相当于从a的起点沿着a+b的方向走a+b的长度。

实际应用:物体的移动。

向量与标量的乘除

乘法:该向量的各分量与标量相乘   k [ x , y , z ] = [ x k , y k , z k ] \ k[x, y, z] = [xk, yk, zk]  k[x,y,z]=[xk,yk,zk]
除法:该向量的各分量与标量相除   [ x , y , z ] / k = [ x / k , y / k , z / k ] \ [x, y, z]/k = [x/k , y/k , z/k]  [x,y,z]/k=[x/k,y/k,z/k]
几何意义:缩放向量长度。

实际应用:加速、减速、放大、缩小。

点乘

点乘又称点积内积。表示为各分量的乘积和。

  [ x 1 , y 1 , z 1 ] ⋅ [ x 2 , y 2 , z 2 ] = x 1 x 2 + y 1 y 2 + z 1 z 2 \ [x1,y1,z1] \cdot [x2,y2,z2] = x1x2+y1y2+z1z2  [x1,y1,z1][x2,y2,z2]=x1x2+y1y2+z1z2

注意结果不是一个向量,而是一个标量(Scalar),可以是负数。

几何意义:   a ⋅ b = ∣ a ∣ ∣ b ∣ cos ⁡ ( a , b ) \ a \cdot b = |a||b|\cos(a, b)  ab=abcos(a,b) 当a、b的模为1时,ab的点乘值为∠ab的cos值,再通过反余弦就可以获得角度。

// 计算点乘值
float dot = Vector3.Dot(a.position.normalized, b.position.normalized);
// 计算夹角
float angle = Mathf.Acos(dot) * Mathf.Rad2Deg;

第一步计算点乘值,第二步计算夹角。

实际应用:计算两向量的夹角。

点乘常用结果:对于标准化后的向量,方向相同,则点乘为1;方向相反,则点乘为-1;互相垂直,则点乘为0。

总结:点乘可以用于计算向量夹角,但只能用于计算内夹角,也就是小于180°的夹角。若想超过180°,则需要与叉乘结合。点乘的结果为单个数值。

叉乘

叉乘又称 “叉积” 或 “外积” ,与点乘结果不同,叉乘结果是一个向量,一个垂直于两个向量所组成平面的向量。模长为两向量模长乘积再乘夹角的正弦值。

公式:   [ x 1 , y 1 , z 1 ] × [ x 2 , y 2 , z 2 ] = [ y 1 ∗ z 1 − z 1 ∗ y 2 , z 1 ∗ x 2 − x 1 ∗ z 2 , x 1 ∗ y 2 − y 1 ∗ x 2 ] \ [x1,y1,z1] \times [x2,y2,z2] = [y1*z1 - z1*y2 , z1*x2 - x1*z2 , x1*y2 - y1*x2]  [x1,y1,z1]×[x2,y2,z2]=[y1z1z1y2,z1x2x1z2,x1y2y1x2]

代码:Vector3 cross = Vector3.Cross(a.position, b.position);
注意:叉乘不需要加normalized,加不加都不会影响结果。

应用:

  1. 创建垂直于平面的向量;
  2. 判断两条向量的相对位置。

叉乘获得垂直向量

  1. 当 a 到 b 顺时针,则 a x b 朝上。

  2. 当 a 到 b 逆时针,则 a x b 朝下。

    也可以这样理解:当a、b顺时针夹角小于180时, a x b 朝上;当a、b顺时针夹角大于180时, a x b 朝下。

代码判断:叉乘结果 y > 0 ,则朝上,则小于180°;叉乘结果 y < 0 ,则朝下,则大于180°;

左手规则

a、b向量叉乘获得的垂直向量遵循左手规则,以下图为例:

以上图手势为标准,垂直于拇指a和食指b形成的平面的向量result就是a、b叉乘的结果。

叉乘计算角度

叉乘也可以用来计算角度,但只能计算0° ~ 90°。

// 计算叉乘结果,叉乘不需要加normalized,但加了也不会有影响
Vector3 cross = Vector3.Cross(a.position, b.position);

// 用叉乘结果换算角度
float angle = Mathf.Asin(cross.magnitude) * Mathf.Rad2Deg;

叉乘常用结果:

计算360°以内的角(点乘结合叉乘)

点乘结合叉乘,可以计算出360°以内的角。

// 先用点乘计算角度(180°以内)
float dot = Vector3.Dot(a.position.normalized, b.position.normalized);
float angleX = Mathf.Acos(dot) * Mathf.Rad2Deg;
// 再用叉乘后的y值确定方向
Vector3 cross = Vector3.Cross(a.position, b.position);
if (cross.y < 0)
{
	angleX = 360 - angleX;
}

先用点乘计算角度(180°以内),再用叉乘后的 y 值确定方向,得数 angleX 为 a 顺时针到 b 的角度。

Vector3

Unity中通常用Vector3类来表示向量,该类的使用方法可以参考我的另外一篇文章:【Unity】Unity常用类:向量Vector3、四元数Quaternion


更多内容请查看总目录【Unity】Unity学习笔记目录整理

有关【Unity】Unity 几何知识、弧度、三角函数、向量运算、点乘、叉乘的更多相关文章

  1. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  2. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

  3. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  4. 旋转矩阵的几何意义 - 2

    点向量坐标矩阵的几何意义介绍旋转矩阵的几何含义之前,先介绍一下点向量坐标矩阵的几何含义点:在一维空间下就是一个标量,如同一条直线上,以任意某一个位置为0点,以一定的尺度间隔为1,2,3...,相反方向为-1,-2,-3...;如此就形成了一维坐标系,这时候任何一个点都可以用一个数值表示,如点p1=5,即即从原点出发沿着x轴正方向移动5个尺度;点p2=-3,负方向移动3个尺度;     在一维坐标系上过原点做垂直于一维坐标系的直线,则形成了二维坐标系,此时描述一个点需要两个数值来表示点p3=(3,2),即从原点出发沿着x轴正方向移动3个尺度,在此基础上沿着y轴正方向移动两个尺度的位置就是点p3。

  5. ruby - 在 Ruby 中按名称传递函数 - 2

    如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只

  6. Unity 热更新技术 | (三) Lua语言基本介绍及下载安装 - 2

    ?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------

  7. FOHEART H1数据手套驱动Optitrack光学动捕双手运动(Unity3D) - 2

    本教程将在Unity3D中混合Optitrack与数据手套的数据流,在人体运动的基础上,添加双手手指部分的运动。双手手背的角度仍由Optitrack提供,数据手套提供双手手指的角度。 01  客户端软件分别安装MotiveBody与MotionVenus并校准人体与数据手套。MotiveBodyMotionVenus数据手套使用、校准流程参照:https://gitee.com/foheart_1/foheart-h1-data-summary.git02  数据转发打开MotiveBody软件的Streaming,开始向Unity3D广播数据;MotionVenus中设置->选项选择Unit

  8. unity---接入Admob - 2

    目录1.AdmobSDK下载地址2.将下载好的unityPackagesdk导入到unity里​编辑 3.解析依赖到项目中

  9. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  10. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

随机推荐