2025Unity中的核心数学工具(二)向量详解(穿插Unity实战相关案例)

 一、向量

1.标量

含义:有数值大小,没有方向

2.向量

含义:有数值大小,有方向的矢量

种类:一维,二维,三维

注意:向量在空间中有无数条,并且可以随意移动

3.向量的计算

A点:(Xa,Ya,Za)                                 B点:(Xb,Yb,Zb)

从A指向B的向量为AB向量 :B-A = (Xb-Xa, Yb-Ya, Zb-Za)

从B指向A的向量为BA向量 :A-B = (Xa-Xb, Ya-Yb, Za-Zb)

计算方法:终点减起点

4.零向量

写法:(0,0,0)

注意:零向量是唯一一个大小为0的向量

5.负向量

写法:(x,y,z)的负向量为(-x,-y,-z)

注意:

(1)负向量和原向量大小相等

(2)负向量和原向量方向相反

6.向量的模长

含义:是向量的长度(向量的模长就是两个点的距离)

模长公式:模长= √x² + y² + z

7.单位向量

含义:模长为1的向量

注意:任意一个向量经过归一化就是单位向量

归一化公式:

(1)模长 = √x² + y² + z²

(2)单位向量 = (x/模长, y/模长, z/模长)


二、向量练习题

1.Unity中判断两点之间距离有几种方式?

(1)使用 Vector3.Distance () 方法

  • 这是 Unity 提供的专门用于计算两点距离的 API
  • 语法:Vector3.Distance(点1的位置, 点2的位置)
  • 代码示例:print(Vector3.Distance(A.position, B.position));

(2)计算两点向量差的模长(magnitude)

  • 先计算两点之间的向量差(点 B - 点 A 或 点 A - 点 B)
  • 再通过向量的 magnitude 属性获取该向量的长度(即两点距离)

2.计算向量(3,4,5)的模长(手写)

3.计算向量 (3,-4) 的单位向量(手写)


三、向量加减乘除

1.向量加法

(1)计算公式

(2)计算意义

【1】两个位置相加没有意义

【2】两个向量相加得到一个新向量

口诀: 向量相加,首尾相连

【3】位置加向量得到一个新位置

口诀: 位置和向量相加=平移位置

2.向量减法

(1)计算公式

(2)意义

【1】两个位置相减得到一个新向量

口诀:两点决定一向量     终点 - 起点

【2】两个向量相减得到一个新向量

口诀:向量相减,头连头,尾指尾    A - B = B头指A头

【3】位置减向量相当于 加负向量

口诀: 位置减向量 = 平移位置

【4】向量减位置没有任何意义

3.向量乘除法

(1)公式

(2)意义


四、向量基础运算练习题

1.题目

        用向量相关知识,实现摄像机跟随(摄像机不设置为对象子物体)

摄像机一直在物体的后方4米,向上偏7米的位置

2.实现

(1)效果

摄像机跟随

(2)代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class test3CameraMove : MonoBehaviour
{
    public float zOffect = 4;
    public float yOffect = 7;
    public Transform target;
    void Start()
    {

    }

    void LateUpdate()
    {
        this.transform.position = target.position + -target.forward * zOffect + target.up * yOffect;

        this.transform.LookAt(target);
    }
}


五、向量点乘

1.点乘计算公式

2.点乘的几何意义

3.点乘公式推导

4.代码演示

(1)补充函数

【1】画线段(前两个参数 分别是 起点 终点

Debug.DrawLine(this.transform.position, this.transform.position + this.transform.forward, Color.red);

【2】画射线(前两个参数 分别是 起点 方向

Debug.DrawRay(this.transform.position, this.transform.forward, Color.white);

(2)通过点乘判断对象方位

float dotResult = Vector3.Dot(this.transform.forward, target.position - this.transform.position);
if( dotResult >= 0 )
{
    print("它在我前方");
}
else
{
    print("它在我后方");
}

(3)通过点乘推导公式算出夹角

  //1.用单位向量算出点乘结果
  dotResult = Vector3.Dot(this.transform.forward, (target.position - this.transform.position).normalized);
  //2.用反三角函数得出角度
  print("角度-" + Mathf.Acos(dotResult) * Mathf.Rad2Deg);

  //Vector3中提供了 得到两个向量之间夹角的方法 
  print("角度2-" + Vector3.Angle(this.transform.forward, target.position - this.transform.position));


六、向量点乘练习题

1.题目

        当一个物体B在物体A前方45度角范围内,并且离A只有5米距离

时,在控制台打印“发现入侵者”

2.实现

(1)演示

检测敌人

(2)代码实现

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class test4Check : MonoBehaviour
{
    public Transform Target;

    private void Update()
    {
        Debug.DrawLine(transform.position, Target.position, Color.red);
        Debug.Log("角度" + Vector3.Angle(this.transform.forward, Target.transform.position - this.transform.position));
        if (Vector3.Distance(this.transform.position, Target.transform.position) <= 5 &&
            Vector3.Angle(this.transform.forward, Target.transform.position - this.transform.position) <= 22.5f)
        {
            print("发现入侵者");
        }
    }
}


七、向量叉乘

1.叉乘计算公式

向量 x 向量 = 向量

        向量A (Xa,Ya,Za)

        向量B (Xb,Yb,Zb)

A x B = (X,Y,Z)

        X = YaZb - ZaYb

        Y = ZaXb - XaZb

        Z = XaYb - YaXb

2.叉乘的几何意义

A x B 得到的向量同时垂直A和B

A x B 向量垂直于A和B组成的平面

A x B = -(B x A)

1.得到一个平面的法向量

Vector3.Cross(A.position, B.position)

2.得到两个向量之间的左右位置关系

//假设向量 A和B 都在 XZ平面上
//向量A 叉乘 向量 B
//y大于0 证明 B在A右侧
//y小于0 证明 B在A左侧



Vector3 C = Vector3.Cross(A.position, B.position);
if( C.y > 0)
{
    print("B在A的右侧");
}
else
{
    print("B在A的左侧");
}


八、向量叉乘的习题

1.题目

(1)判断一个物体B位置再另一个物体A的位置的左上,左下 ,右上,右下哪个方位

(2)当一个物体B在物体A左前方20度角或右前方30度范围内,并且离A只有5米距离时, 在控制台打印“发现入侵者

2.实现

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FindEnemy2 : MonoBehaviour
{
    public Transform A;
    public Transform B;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    private float dotResult;
    private Vector3 crossResult;
    // Update is called once per frame
    void Update()
    {
        //第一题
        dotResult = Vector3.Dot(A.forward, B.position - A.position);
        crossResult = Vector3.Cross(A.forward, B.position - A.position);
        //判断前后
        if (dotResult >= 0 )
        {
            //右侧
            if(crossResult.y >= 0)
            {
                print("右前");
            }
            //左侧
            else
            {
                print("左前");
            }
        }
        else
        {
            //右侧
            if (crossResult.y >= 0)
            {
                print("右后");
            }
            //左侧
            else
            {
                print("左后");
            }
        }

        //第二题
        if( Vector3.Distance(A.position, B.position) <= 5 )
        {
            if( crossResult.y >= 0 && Vector3.Angle(A.forward, B.position - A.position) <= 30 ||
                crossResult.y < 0 && Vector3.Angle(A.forward, B.position - A.position) <= 20)
            {
                print("发现入侵者");
            }
        }
    }
}


九、向量插值运算

1.线性插值

(1)语法
Vector3.Lerp(start, end, t);

 //1.先快后慢 每帧改变start位置 位置无限接近 但不会得到end位置
 A.position = Vector3.Lerp(A.position, target.position, Time.deltaTime);

 //2.匀速 每帧改变时间  当t>=1时 得到结果
 //这种匀速移动 当time>=1时  我改变了 目标位置后  它会直接瞬移到我们的目标位置
 if(nowTarget != target.position)
 {
     nowTarget = target.position;
     time = 0;
     startPos = B.position;
 }
 time += Time.deltaTime;
 B.position = Vector3.Lerp(startPos, nowTarget, time);
 #endregion

(2)意义

对两个点进行插值计算      t的取值范围为0~1

(3)公式

公式:result = start + (end - start) * t

(4)应用

1.每帧改变start的值(先快后慢)

2.每帧改变t的值(匀速)

2.球形插值

(1)语法

Vector3.Slerp(start, end, t);

C.position = Vector3.Slerp(Vector3.right * 10, Vector3.left * 10 + Vector3.up*0.1f, time*0.01f);

(2)意义

对两个向量进行插值计算      t的取值范围为0~1

(3)区别


十、向量插值练习题

1.题目

2.实现

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraMove : MonoBehaviour
{
    public float zOffect = 4;
    public float yOffect = 7;
    public Transform target;

    private Vector3 targetPos;
    public float moveSpeed;
    private Vector3 startPos;
    private float time;
    // Start is called before the first frame update
    void Start()
    {
        
    }

    void LateUpdate()
    {
        //先快后慢的移动
        //if(targetPos != target.position + -target.forward * zOffect + target.up * yOffect)
        //{
        //    targetPos = target.position + -target.forward * zOffect + target.up * yOffect;
        //}
        ////摄像机的位置 等于目标的位置 进行向量偏移
        ////先朝目标对象的 面朝向的反方向平移4米 再朝目标的头顶位置 平移7米
        //this.transform.position = Vector3.Lerp(this.transform.position, targetPos, Time.deltaTime*moveSpeed);

        //匀速移动
        if (targetPos != target.position + -target.forward * zOffect + target.up * yOffect)
        {
            targetPos = target.position + -target.forward * zOffect + target.up * yOffect;
            startPos = this.transform.position;
            time = 0;
        }
        time += Time.deltaTime;
        this.transform.position = Vector3.Lerp(startPos, targetPos, time* moveSpeed);

        this.transform.LookAt(target);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值