jjzjj

【学习笔记】unity脚本学习(三)(向量 Vector3)

|Ringleader| 2024-04-09 原文

目录


新的一周,开启新的学习,加油

向量复习

视频讲得笼统了,还是去复习下高中知识吧

高中向量基础

高中数学平面向量


【数学】向量的四则运算、点积、叉积、正交基

叉乘公式

向量点乘(内积)和叉乘(外积、向量积)概念及几何意义解读
两个向量的叉乘,又叫向量积、外积、叉积,叉乘的运算结果是一个向量而不是一个标量。并且两个向量的叉积与这两个向量组成的坐标平面垂直。
对于向量a和向量b:
a和b的叉乘公式为:

其中:
根据i、j、k间关系,有:

叉乘运算定理

向量外积的高中数学运用

向量、坐标系

  • 向量、标量
    标量就是向量的模(取平方根)
  • 右手坐标系、左手坐标系

    unity用的是左手坐标系

点积


unity提供点积函数 Vector3.Dot(VectorA,VectorB)
点积的应用:

比如用游戏中飞机的forward和世界坐标up进行点积,为0也就是垂直,那么就给它最小的空气阻力,否则加大空气阻力。

叉积

数学上方向用右手螺旋来判断:

unity中用左手来判断?这点再继续搜查一下!

unity中叉积函数Vector3.Cross(VectorA,VectorB)

应用:

如上:坦克原先朝向A,想在想瞄准B方向,那么就可以A^B,得到垂直的C向量,对C轴进行旋转就能方便地操作物体

Vector3 三维向量

官网Vector3API

静态变量

变量

  • magnitude 返回该向量的长度。(只读)
  • normalized 返回 magnitude 为 1 时的该向量。(只读)
  • sqrMagnitude 返回该向量的平方长度。(只读)
  • this[int] 分别使用 [0]、[1]、[2] 访问 x、y、z 分量。

变量normalized 与 Normalize() 方法

normalized 返回 magnitude 为 1 时的该向量。(只读)

进行标准化时,向量方向保持不变,但其长度为 1.0。
请注意,当前向量保持不变,返回一个新的归一化向量。如果 要归一化当前向量,请使用 Normalize 函数。
如果向量太小而无法标准化,则返回零向量。

Normalize 使该向量的 magnitude 为 1。
请注意,此函数将更改当前向量。如果 要保持当前向量不变,请使用 normalized 变量。
如果该向量太小而无法标准化,则将其设置为零。

Vector3 v1;
    Vector3 v2;
    // Start is called before the first frame update
    private void Awake() {
        v1 = transform.position;
    }
    void Start()
    {
        v2 = v1.normalized;
        // v2 = Vector3.Normalize(v1);
        // v1.Normalize();
        Debug.Log("the value of v1:"+ v1.ToString() + " and v1 Magnitude:"+ v1.magnitude.ToString());
        Debug.Log("the value of v2:"+ v2.ToString() + " and v2 Magnitude:"+ v2.magnitude.ToString());
    }

v2 = v1.normalized;执行结果

v2 = Vector3.Normalize(v1);执行结果

v1.Normalize();执行结果

可以看到,只有v1.Normalize()才会对向量本身产生影响,Vector3.Normalize(v1)v1.normalized都会生成新的向量。

静态方法

ClampMagnitude

public static Vector3 ClampMagnitude (Vector3 vector, float maxLength);
返回 vector 的副本,其大小被限制为 maxLength

    public float radius = 1;
    Vector3 v;
    // Update is called once per frame
    void Update()
    {
        transform.position = Vector3.ClampMagnitude(transform.position, radius);   
    }
    private void OnGUI() {
        v = transform.position;
        GUILayout.TextArea("vector:"+ v.ToString() +" ClampMagnitude:" + v.magnitude.ToString());
    }


可以看到物体被限制在1的范围内(原点为中心,1为半径活动)

Cross

public static Vector3 Cross (Vector3 lhs, Vector3 rhs);
两个向量的叉积。
两个向量的叉积生成第三个向量, 该向量垂直于两个输入向量。结果的大小等于: 将两个输入的大小相乘,然后乘以输入之间角度的正弦值,即|a||b|sinθ。 可以使用“左手规则”确定结果向量的方向。

   Vector3 cross;

    // Update is called once per frame
    void Update()
    {
        cross = Vector3.Cross(transform.position,Vector3.up);
        Debug.DrawLine(Vector3.zero ,transform.position, Color.blue);
        Debug.DrawLine(Vector3.zero ,Vector3.up, Color.green);
        Debug.DrawLine(Vector3.zero ,cross, Color.red);
    }

Distance

public static float Distance (Vector3 a, Vector3 b);
返回 a 与 b 之间的距离。

Vector3.Distance(a,b) 与 (a-b).magnitude 相同。

【注意理解:向量表示的是大小和方向,与位置无关】

Dot

public static float Dot (Vector3 lhs, Vector3 rhs);
两个向量的点积

点积是一个浮点值,它等于 将两个向量的大小相乘,然后乘以向量之间角度的余弦值。
对于 normalized 向量,如果它们指向完全相同的方向,Dot 返回 1; 如果它们指向完全相反的方向,返回 -1;如果向量彼此垂直,则 Dot 返回 0。

MoveTowards

public static Vector3 MoveTowards (Vector3 current, Vector3 target, float maxDistanceDelta);
计算 current 指定的点与 target 指定的点之间的位置,移动距离不超过 maxDistanceDelta 指定的距离。

        // Move our position a step closer to the target.
        var step =  speed * Time.deltaTime; // calculate distance to move
        transform.position = Vector3.MoveTowards(transform.position, target.position, step);

【这里我原来比较难以理解的是,向量不应该是与位置无关的吗,为什么还能标定起始点还有移动这种概念。我自己理解了下,这个Vector3 的moveTowards 实际上就是沿着(target - current)方向进行移动,移动大小不超过|target - current|和maxDistanceDelta,所以说还是向量的方向和大小的概念,所谓的位置改变针对的是position而已,更像是对物体施加一个力,力只有方向和大小,与位置无关,只是这个力使物体产生了位移了罢】

其他变换类似

Lerp 在两个点之间进行线性插值。
RotateTowards 将向量 current 朝 target 旋转。
Slerp 在两个向量之间进行球形插值。
SmoothDamp 随时间推移将一个向量逐渐改变为所需目标。

Max

public static Vector3 Max (Vector3 lhs, Vector3 rhs);
返回由两个向量的最大分量组成的向量。

 // prints (4.0f, 3.0f, 3.0f)
print(Vector3.Max(new Vector3(1, 2, 3), new Vector3(4, 3, 2)));

Min

返回由两个向量的最小分量组成的向量。

Scale

将两个向量的分量相乘。

// This will compute Vector3(2, 6, 12)
print(Vector3.Scale(new Vector3(1, 2, 3), new Vector3(2, 3, 4)));

下面是比较不好理解的几个

OrthoNormalize 将向量标准化并使它们彼此正交。

public static void OrthoNormalize (ref Vector3 normal, ref Vector3 tangent);
public static void OrthoNormalize (ref Vector3 normal, ref Vector3 tangent, ref Vector3 binormal);
将向量标准化并使它们彼此正交。
标准化 tangent。 标准化 tangent 并确保其与 normal 正交(即它们之间的角度为 90 度)。

    public Transform obj1;
    public Transform obj2;
    Vector3 a,b,c,d,e,f;

    // Update is called once per frame
    void Update()
    {
        a =transform.position;
        b = obj1.position;
        c = obj2.position;
        d = a;
        e = b;
        f = c;
        Vector3.OrthoNormalize(ref a, ref b, ref c);
        Debug.DrawLine(Vector3.zero,d,Color.yellow);
        Debug.DrawLine(Vector3.zero,e,Color.white);
        Debug.DrawLine(Vector3.zero,f,Color.black);
        Debug.DrawLine(Vector3.zero,a,Color.red);
        // 注:绿色切线我延长了,方便观察
        Debug.DrawLine(Vector3.zero,b*10,Color.green);
        Debug.DrawLine(Vector3.zero,c,Color.blue);
        Debug.DrawLine(d,e,Color.grey);
    }


从图中可以看到,生成的切线、次法线只与第一和第二个参数有关,所以提供了一个两个参数的函数。
其中生成的切线(绿色)与 向量a和向量b同平面,且垂直于向量a,生成的次法线(蓝线)垂直于法线(红线)与切线(绿线)。

Project 将向量投影到另一个向量上。

public static Vector3 Project (Vector3 vector, Vector3 onNormal);

    public Transform target;
    public Vector3 rail;
    private void Update() {
        Vector3 heading = target.position-transform.position;
        Vector3 project = Vector3.Project(heading,rail);
        Debug.DrawLine(transform.position,target.position,Color.green);
        Debug.DrawLine(transform.position,transform.position + project,Color.red);
    }

ProjectOnPlane 将向量投影到由法线定义的平面上(法线与该平面正交)。

public static Vector3 ProjectOnPlane (Vector3 vector, Vector3 planeNormal);
两个投影和数学概念一致

public Transform target;
    public Vector3 rail;
    private void Update() {
        Vector3 heading = target.position-transform.position;
        Vector3 project = Vector3.ProjectOnPlane(heading,rail);
        Debug.DrawLine(transform.position,target.position,Color.green);
        Debug.DrawLine(transform.position,transform.position + project,Color.red);
        Debug.DrawLine(transform.position,transform.position+rail,Color.white);        
    }

Reflect 从法线定义的平面反射一个向量。

public static Vector3 Reflect (Vector3 inDirection, Vector3 inNormal);

public Transform target;
    public Vector3 rail;
    private void Update() {
        Vector3 heading = transform.position-target.position;
        Vector3 reflect = Vector3.Reflect(heading,rail);
        Debug.DrawLine(transform.position,target.position,Color.green);
        Debug.DrawLine(transform.position,transform.position + reflect,Color.red);   
        Debug.DrawLine(Vector3.zero +transform.position,transform.position + rail,Color.white);    
    }

结言

ok,花了两天终于把Vector搞完了,内容也挺多的,之前transform没懂的部分在这块也补充了。
加油!继续输入输出~

有关【学习笔记】unity脚本学习(三)(向量 Vector3)的更多相关文章

  1. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  2. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

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

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

  4. 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

  5. unity---接入Admob - 2

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

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

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

  7. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  8. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

  9. CAN协议的学习与理解 - 2

    最近在学习CAN,记录一下,也供大家参考交流。推荐几个我觉得很好的CAN学习,本文也是在看了他们的好文之后做的笔记首先是瑞萨的CAN入门,真的通透;秀!靠这篇我竟然2天理解了CAN协议!实战STM32F4CAN!原文链接:https://blog.csdn.net/XiaoXiaoPengBo/article/details/116206252CAN详解(小白教程)原文链接:https://blog.csdn.net/xwwwj/article/details/105372234一篇易懂的CAN通讯协议指南1一篇易懂的CAN通讯协议指南1-知乎(zhihu.com)视频推荐CAN总线个人知识总

  10. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

随机推荐