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

1、Unity【基础】3D数学

3D数学

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

文章目录

  • 3D数学
    • 1、数学计算公共类Mathf
      • 1、Mathf和Math
      • 2、区别
      • 3、Mathf中的常用方法(一般计算一次)
      • 4、Mathf中的常用方法(一般不停计算)
      • 练习 A物体跟随B物体移动
    • 2、三角函数
      • 1、角度和弧度
      • 2、三角函数
      • 3、反三角函数
      • 练习 物体曲线移动
    • 3、Unity中的坐标系
      • 1、世界坐标系
      • 2、物体坐标系
      • 3、屏幕坐标系
      • 4、视口坐标系
      • 5、坐标转换
    • 4、Vector3向量
      • 1、向量模长和单位向量
        • 1、向量基础
        • 2、两点决定 向量
        • 3、零向量和负向量
        • 4、向量模长
        • 5、单位向量
      • 2、向量加减乘除
        • 练习:向量实现摄像机跟随
      • 3、向量点乘
        • 1、点乘的计算
        • 2、点乘的几何意义
        • 3、公式推导
        • 4、通过点乘推导公式算出夹角
        • 练习 检测半径为5,角度为90°的扇形区域
      • 4、向量叉乘
        • 1、叉乘计算公式
        • 2、几何意义
        • 练习 物体方位
      • 5、差值运算
        • 1、线性插值
          • 两种线性插值代码实现
        • 2、球性插值
        • 思考1 Lerp摄像机跟随
        • 思考2 球形插值模拟太阳升降
    • 5、Quaternion四元数
      • 1、为何使用四元数
      • 2、四元数是什么
        • 1、四元数的构成
        • 2、Unity中的四元数
        • 3、四元数和欧拉角转换
        • 4、四元数弥补欧拉角的缺点
      • 3、四元数常用方法
        • 1、单位四元数
        • 2、插值运算
        • 3、向量方向 转换为对应 四元数角度
        • 思考1 写一个类似LookAt()的拓展方法
        • 思考2 用LookRotation实现摄像机跟随
      • 4、四元数计算
        • 1、四元数相乘
        • 2、四元数乘向量
        • 思考1 模拟飞机发射子弹,单发、双发、扇形、环形
        • 思考2 摄像机跟随效果

3D数学

1、数学计算公共类Mathf

1、Mathf和Math

Math是c#中封装好的用于【数学计算的工具类】位于system命名空间中public static class Math{}
Mathf是Unity中封装好的用于【数学计算的工具结构体】位于UnityEngine命名空间中public struct Mathf{}
他们都是提供来用于进行【数学相关计算】的

2、区别

一个是静态类,一个是结构体
Mathf比Math有更多的数学计算方法

3、Mathf中的常用方法(一般计算一次)

void Start()
{1、π PIMathf.PI2、绝对值 Abs3、向上取整 CeilToIntprint(Mathf.CeilToInt(1.3f)); //24、向下取整 FloorToInt5、钳制函数 Clamp (在参数二,和参数三的范围里取值)print(Mathf.Clamp(10, 11, 22)); //11print(Mathf.Clamp(23, 11, 22)); //22print(Mathf.Clamp(16, 11, 22)); //166、获取最大值 Max7、获取最小值 Min8、一个数的n次方 Powprint(Mathf.Pow(2, 3)); //2的3次方9、四舍五入 RoundToInt10、返回一个数的平方根 Sqrt11、判断一个数是否是2的n次方 IsPowerOfTwoprint(Mathf.IsPowerOfTwo(1)); //true12、判断正负数 Signprint(Mathf.Sign(8)); //1print(Mathf.Sign(-8)); //-1
}

4、Mathf中的常用方法(一般不停计算)

float start = 0;
float result = 0;
float time = 0;
void Update()
{
插值运算 LerpLerp函数公式result = Mathf.Lerp(start,end,t);t为插值系数,取值范围为0~1,计算方法:result = start + (end - start) * t插值运算用法1每帧改变start的值:变化速度先快后慢,位置无限接近,但是不会得到end位置//此处相当于log函数start = Mathf.Lerp(start, 10, Time.deltaTime);插值运算用法2每帧改变t的值:变化速度匀速,每帧接近,当t>=1时,得到结果//此处相当于正比例函数time += Time.deltaTime;result = Mathf.Lerp(result, 10, time);
}

练习 A物体跟随B物体移动

using UnityEngine;public class FollowCube : MonoBehaviour
{public Transform B;public float moveSpeed = 1;private Vector3 pos;private Vector3 bNowPos;private Vector3 startPos;private float time;void Update(){//先快后慢//pos = transform.position;//pos.x = Mathf.Lerp(pos.x, B.position.x, Time.deltaTime * moveSpeed);//pos.y = Mathf.Lerp(pos.y, B.position.y, Time.deltaTime * moveSpeed);//pos.z = Mathf.Lerp(pos.z, B.position.z, Time.deltaTime * moveSpeed);//transform.position = pos;//匀速运动if (bNowPos!= B.transform.position){time = 0;bNowPos = B.transform.position;startPos= transform.position;}time += Time.deltaTime;pos.x = Mathf.Lerp(startPos.x, bNowPos.x, time * moveSpeed);pos.y = Mathf.Lerp(startPos.y, bNowPos.y, time * moveSpeed);pos.z = Mathf.Lerp(startPos.z, bNowPos.z, time * moveSpeed);transform.position = pos;}
}

2、三角函数

1、角度和弧度

1.角度和弧度角度:1°弧度:1 (radian)圆一周的弧度:2π (radian)2.角度和弧度的关系π rad = 180°则:1 rad ≈ 57.3°1° ≈ 0.01745 rad角度 = 弧度 * 57.3float rad = 1;float angle = rad * Mathf.Rad2Deg;弧度 = 角度 * 0.01745angle = 1;rad = angle * Mathf.Deg2Rad;

2、三角函数

Mathf中,只使用弧度,所以要角度转弧度(Deg2Rad)
sin30°Mathf.Sin(30 * Mathf.Deg2Rad);

3、反三角函数

通过反三角函数计算正弦值或余弦值对应的弧度值弧度 = Mathf.Asin(正弦值)弧度 = Mathf.Acos(余弦值)float radian = Mathf.Asin(0.5f);   //先将值转化为弧度float degree = radian * Mathf.Rad2Deg;   //再将弧度转角度print(degree);

练习 物体曲线移动

using UnityEngine;public class SinMove : MonoBehaviour
{public float moveSpeed = 1; //前后移动public float changeSpeed = 2; //左右移动public float changeSize = 5; //左右幅度private float time = 0;void Update(){    time += Time.deltaTime * changeSpeed;//前后移动transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);//左右移动transform.Translate(Vector3.right * changeSize * Time.deltaTime * Mathf.Sin(time));}
}

3、Unity中的坐标系

1、世界坐标系

原点:世界的中心点
轴向:世界坐标系的三个轴向是固定的transform.position;transform.rotation;transform.eulerAngles; //欧拉角transform.lossyScale; //缩放

2、物体坐标系

原点:物体的中心点(建模时决定)
轴向:物体的方右为x轴正方向物体的上方为y轴正方向物体的前方为z轴正方向//相对父对象的坐标transform.localPosition;transform.localRotation;transform.localEulerAngles;transform.localScale;

3、屏幕坐标系

原点:屏幕左下角
轴向:向右为x轴正方向向上为y轴正方向
最大宽高:Input.mousePosition;Screen.width;Screen.height;

4、视口坐标系

原点:屏幕左下角
轴向:向右为x轴正方向向上为y轴正方向
特点:左下角(0,0)右上角(1,1)
和屏幕坐标类似,将坐标单位化
摄像机上的【视口范围】属于视口 Viewport Rect

5、坐标转换

世界转本地transform.InverseTransformDirection;transform.InverseTransformPoint;transform.InverseTransformVector;本地转世界transform.TransformDirection;transform.TransformPoint;transform.TransformVector;世界转屏幕Camera.main.WorldToScreenPoint;
屏幕转世界Camera.main.ScreenToWorldPoint;世界转视口Camera.main.WorldToViewportPoint;
视口转世界Camera.main.ViewportToWorldPoint;视口转屏幕Camera.main.ViewportToScreenPoint;
屏幕转视口Camera.main.ScreenToViewportPoint;

4、Vector3向量

1、向量模长和单位向量

1、向量基础
三维向量 Vector3
Vector3有两种意义:1、可以表示位置 代表一个点transform.position;2、也可以表示方向 代表一个方向transform.forward;
2、两点决定 向量
Vector3 A = new Vector3(1, 2, 3);
Vector3 B = new Vector3(2, 3, 4);
求向量 终点 - 起点
Vector3 AB = B - A;
Vector3 BA = A - B;
3、零向量和负向量
零向量(0,0,0)Vector3.zero;
负向量(x,y,z)的负向量为(-x,-y,-z)Vector3.forward;-Vector3.forward;
4、向量模长
模长:向量的长度AB.magnitude; //AB的模长Vector3 C = new Vector3(3, 4, 5);print(C.magnitude); //点C到原点的模长Vector3.Distance(A, B); //两点之间的距离
5、单位向量
模长为1的向量只管方向AB.normalized;AB / AB.magnitude;

2、向量加减乘除

1、向量加法:位置+位置:Unity无意义向量+向量:首位相连位置+向量:平移位置transform.Translate(Vector3.forward * 5);//transform.position += new Vector3(1, 2, 3);2、向量减法:位置-位置:向量向量-向量:新向量 (A-B=B向量头指向A向量头)位置-向量:平移位置transform.Translate(-Vector3.forward * 5);//transform.position -= new Vector3(1, 2, 3);3、向量的乘除向量 */ 标量 = 缩放向量的模长transform.localScale *= 2;transform.localScale /= 2;//LossyScale只能得,不能改
练习:向量实现摄像机跟随
public float z = 4;
public float y = 7;
public Transform target;void LateUpdate()
{//摄像机移动在LateUpdate中transform.position = target.position + -target.forward * z + target.up * y;transform.LookAt(target);
}

3、向量点乘

1、点乘的计算
向量A(Xa,Ya,Za)
向量B(Xb,Yb,Zb)A*B = Xa*Xb + Ya*Yb + Za*Zb
向量 * 向量 = 标量
2、点乘的几何意义
点乘可以得到向量的投影长度
点乘结果>0,两个向量的夹角为锐角 (目标在前)
点乘结果=0,两个向量的夹角为直角 (目标在左or右两侧不确定)
点乘结果<0,两个向量的夹角为钝角 (目标在后)
作用:判断目标的大致方位

unity点乘

调试画线//线段 参数(起点,终点)Debug.DrawLine(transform.position, transform.position + transform.forward * 3, Color.red);//射线 参数(起点,方向)Debug.DrawRay(transform.position,transform.right, Color.green);
通过点乘判断对象方位//得到两个向量的点乘结果Debug.DrawRay(transform.position, transform.forward * 10);Debug.DrawRay(transform.position, target.position - transform.position);float a = Vector3.Dot(transform.forward, target.position - transform.position);if (a >= 0){print("目标在前方");}else{print("目标在后方");}
3、公式推导
已知单位模长A 单位模长B,以及点乘的几何意义;
则:cosβ = 单位向量A * 单位向量B
再根据数学的反三角函数推出:β = Mathf.Acos(A*B) * Mathf.Rad2Deg
4、通过点乘推导公式算出夹角
//单位向量算出点乘结果(方向向量)
float dotResult = Vector3.Dot(transform.forward, (target.position - transform.position).normalized);
//用Unity反三角函数算出角度
print(Mathf.Acos(dotResult) * Mathf.Rad2Deg);最简单直接的方法:
//Unity只需两个向量算出夹角的方法
float ang = Vector3.Angle(transform.forward, target.position - transform.position);
print("角度" + ang);
练习 检测半径为5,角度为90°的扇形区域
方法一:
public Transform B;
void Update()
{float c = Vector3.Distance(transform.position, B.position);if (c <= 5){float dotResult = Vector3.Dot(transform.forward, (B.position - transform.position).normalized);//Debug.DrawRay(transform.position, (transform.forward + Vector3.right)*5);if ((Mathf.Acos(dotResult) * Mathf.Rad2Deg) <= 45f){print("发现目标");print("与目标距离" + c + "米");}}
}
方法二: 用Angle
public Transform B;
void Update()
{float c = Vector3.Distance(transform.position, B.position);if (c <= 5 && Vector3.Angle(transform.position, B.position - transform.position) <= 45){print("发现目标");print("与目标距离" + c + "米");}
}

4、向量叉乘

1、叉乘计算公式
向量 * 向量 = 向量向量A(Xa,Ya,Za)向量B(Xb,Yb,Zb)A*B=(X,Y,Z)X = Ya*Zb - Za*YbY = Za*Xb - Xa*ZbZ = Xa*Yb - Ya*XbVector3.Cross();
2、几何意义
A*B得到的向量同时垂直A和B的法向量
A*B = - B*A若A、B向量在同一平面上,A*B(y为法向量):
y>=0;则B在A的右侧
y<0;则B在A的左侧总结:根据向量叉乘的顺序决定左右位置Vector3 cross = Vector3.Cross(A.position, B.position);if (cross.y > 0){print("B在A的右侧");}else{print("B在A的左侧");}
练习 物体方位
1//判断物体B相对于物体A的位置,左上,左下,右上,右下方位
public Transform A;
public Transform B;//点乘判断前后
private float dotResult;
//叉乘判断左右
private float crossResult;private float distance; //距离
private float angle; //角度void Update()
{dotResult = Vector3.Dot(A.forward, B.position - A.position);crossResult = Vector3.Cross(A.forward, B.position - A.position).y;//点乘判断前后if (dotResult >= 0){//前print(crossResult >= 0 ? "B在右上方" : "B在左上方");}else{//后print(crossResult >= 0 ? "B在右后方" : "B在左后方");}2//判断一个物体在左前方20度角or右前方30度范围内,且在距离5米内distance = Vector3.Distance(A.position, B.position);angle = Vector3.Angle(A.forward, B.position - A.position);if (distance <= 5){if (crossResult >= 0 && angle <= 30){print("发现目标!!!");print("目标位于右前方" + decimalPoint2(angle) + "°," + decimalPoint2(distance) + "米处");}else if (crossResult < 0 && angle <= 20){print("发现目标!!!");print("目标位于左前方" + decimalPoint2(angle) + "°," + decimalPoint2(distance) + "米处");}}
}//小数点保留后两位
private float decimalPoint2(float f)
{int i = (int)(f * 100);return i * 0.01f;
}

5、差值运算

1、线性插值
Vector3.Lerp(start, end, t);
对两个点进行插值计算
t的取值范围为0~1计算公式:result = start + (end - start) * t应用1、每帧改变start的值(先快后慢)2、每帧改变t的值(匀速)
两种线性插值代码实现
public Transform A;
public Transform B;
public Transform target;private Vector3 startPos;
private float time;
private Vector3 nowTarget;void Start()
{startPos = B.position;
}void Update()
{//每帧改变start的值(先快后慢)A.position = Vector3.Lerp(A.position, target.position, Time.deltaTime);//每帧改变t的值(匀速)if (nowTarget != target.position){nowTarget = target.position;startPos = B.position;time = 0;}time += Time.deltaTime;B.position = Vector3.Lerp(startPos, nowTarget, time);
}
2、球性插值
Vector3.slerp(start, end, t);
对两个向量进行插值运算 t:(0~1)
//运动轨迹为弧形
C.position = Vector3.Slerp(transform.forward * 10, -transform.forward * 3, time);
思考1 Lerp摄像机跟随
1.先快后慢
public float z = 4;
public float y = 7;
public Transform target;public Vector3 targetPos;
public int speedMove = 1;void LateUpdate()
{//目标位置if (targetPos != target.position + -target.forward * z + target.up * y){targetPos = target.position + -target.forward * z + target.up * y;}transform.position = Vector3.Lerp(transform.position, targetPos, Time.deltaTime * speedMove);transform.LookAt(target);
}
2、匀速跟随
public float z = 4;
public float y = 7;
public Transform target;public Vector3 targetPos;
public int speedMove = 1;
private Vector3 startPos;
private float time;
void LateUpdate()
{//目标位置if (targetPos != target.position + -target.forward * z + target.up * y){targetPos = target.position + -target.forward * z + target.up * y;startPos = transform.position;time = 0;}time += Time.deltaTime;transform.position = Vector3.Lerp(startPos, targetPos, time*speedMove);transform.LookAt(target);
}
思考2 球形插值模拟太阳升降
public Transform C;
private float time;
void Update()
{time += Time.deltaTime;C.position = Vector3.Slerp(Vector3.right*10 + Vector3.up * 0.1f, Vector3.left*10, time*0.1f);
}

5、Quaternion四元数

1、为何使用四元数

Rotation表示欧拉角 transform.eulerAngles
因为欧拉角存在一些缺点:
1、同一旋转的表示不唯一
2、万向节死锁
而四元数旋转不存在万向节死锁问题
所以使用四元数来表示三维空间中的旋转信息

2、四元数是什么

1、四元数的构成
四元数包含一个标量和一个3D向量
[w,v] w为标量,v为3D向量
[w,(x,y,z)]
四元数表示3D空间中的一个旋转量轴-角对(含义):绕一个轴(Q)旋转β度
2、Unity中的四元数
Unity中的四元数:Quaternion
轴角对初始化
1、基本写法(很少用):公式:四元数Q = [cos(β/2),sin(β/2)*x,sin(β/2)*y,sin(β/2)*z]简化记忆:Q = c,s(x,y,z)  β/2//(1,0,0)旋转60度Quaternion q = new Quaternion(Mathf.Cos(60 / 2 * Mathf.Deg2Rad), 0, 0, Mathf.Sin(60 / 2 * Mathf.Deg2Rad) * 1);2、Unity简单写法依据公式:四元数Q = Quaternion.AngleAxis(角度,);Unity代码:Quaternion q = Quaternion.AngleAxis(60,Vector3.right);//将四元数赋值给一个物体GameObject obj = GameObject.CreatePrimitive(PrimitiveType.Cube);obj.transform.rotation = q;
3、四元数和欧拉角转换
1、欧拉角转四元数
Quaternion q = Quaternion.Euler(60,0,0);
2、四元数转欧拉角
q.eulerAngles;
4、四元数弥补欧拉角的缺点
四元数相乘:旋转四元数
1、四元数的结果始终是 -180~180
2、四元数旋转可以避免万向节死锁

3、四元数常用方法

1、单位四元数
没有旋转量(角位移)
Unity:Quaternion.identity
例:[1,(0,0,0)][-1,(0,0,0)]
作用:对象角度初始化
2、插值运算
// Slerp比Lerp效果好
public Transform A;
public Transform B;
public Transform C;private Quaternion start;
private float time;
void Start()
{start = B.rotation;
}void Update()
{//先快后慢,无线接近A.rotation = Quaternion.Slerp(A.rotation, C.rotation, Time.deltaTime);//匀速变化 time>=1则到达目标time += Time.deltaTime;B.rotation = Quaternion.Slerp(start, C.rotation, time);
}
3、向量方向 转换为对应 四元数角度
API:Quaternion.LookRotation(目标向量)public Transform LA;
public Transform LB;
void Update()
{LA.rotation = Quaternion.LookRotation(LB.position - LA.position);
}
思考1 写一个类似LookAt()的拓展方法
public static class Tool
{public static void MyLookAt(this Transform obj,Transform target){obj.rotation = Quaternion.LookRotation(target.position - obj.position);}
}
思考2 用LookRotation实现摄像机跟随
public float z = 4;
public float y = 7;
public Transform target;
public Vector3 targetPos;public int speedMove = 1;
private Vector3 startPos;
private float time;private Quaternion targetQua;private Quaternion startQua;
private float roundTime;
void LateUpdate()
{//目标位置if (targetPos != target.position + -target.forward * z + target.up * y){targetPos = target.position + -target.forward * z + target.up * y;startPos = transform.position;time = 0;}time += Time.deltaTime;transform.position = Vector3.Lerp(startPos, targetPos, time * speedMove);//transform.LookAt(target);//1、先快后慢//targetQua = Quaternion.LookRotation(target.position - transform.position);//transform.rotation = Quaternion.Slerp(transform.rotation, targetQua, Time.deltaTime);//2、匀速跟随if (targetQua != Quaternion.LookRotation(target.position - transform.position)){targetQua = Quaternion.LookRotation(target.position - transform.position);startQua = transform.rotation;roundTime = 0;}roundTime += Time.deltaTime;transform.rotation = Quaternion.Slerp(startQua, targetQua, roundTime);
}

4、四元数计算

1、四元数相乘
q1 = q2 * q3
两个旋转量的叠加
旋转方向一直是本地坐标系Quaternion qua = Quaternion.AngleAxis(30, Vector3.up);
transform.rotation *= qua; //沿y轴顺时针旋转30度
transform.rotation *= qua; //再旋转30度
2、四元数乘向量
V1 = v2 * q
旋转【四元数角度】向量Vector3 v = Vector3.forward;
v = Quaternion.AngleAxis(45, Vector3.up) * v; //此处必须:先四元数,再乘向量
思考1 模拟飞机发射子弹,单发、双发、扇形、环形

AirPlane 飞机类

using UnityEngine;public enum E_FireType
{SingleShoot,DoubleShoot,SectorShoot,AnnularShoot
}
public class AirPlane : MonoBehaviour
{public GameObject bullet;public int bulletNum = 4;private E_FireType nowType = E_FireType.SingleShoot;void Update(){if (Input.GetKeyDown(KeyCode.Alpha1)){print("切换为单发");nowType = E_FireType.SingleShoot;}if (Input.GetKeyDown(KeyCode.Alpha2)){print("切换为双发");nowType = E_FireType.DoubleShoot;}if (Input.GetKeyDown(KeyCode.Alpha3)){print("切换为扇形子弹");nowType = E_FireType.SectorShoot;}if (Input.GetKeyDown(KeyCode.Alpha4)){print("切换为环形子弹");nowType = E_FireType.AnnularShoot;}if (Input.GetKeyDown(KeyCode.Space)){print("开火");Fire();}}private void Fire(){switch (nowType){case E_FireType.SingleShoot:Instantiate(bullet,transform.position,transform.rotation);break;case E_FireType.DoubleShoot:Instantiate(bullet, transform.position - transform.right * 0.5f, transform.rotation);Instantiate(bullet, transform.position + transform.right * 0.5f, transform.rotation);break;case E_FireType.SectorShoot:Instantiate(bullet, transform.position, transform.rotation);Instantiate(bullet, transform.position, transform.rotation * Quaternion.AngleAxis(-15, Vector3.up));Instantiate(bullet, transform.position, transform.rotation * Quaternion.AngleAxis(15, Vector3.up));break;case E_FireType.AnnularShoot:float angle = 360 / bulletNum;for (int i = 0; i < bulletNum; i++)Instantiate(bullet,transform.position,transform.rotation*Quaternion.AngleAxis(i* angle, Vector3.up));break;}}
}

Bullet 子弹类

using UnityEngine;public class Bullet : MonoBehaviour
{public float moveSpeed = 10;private void Start(){Destroy(gameObject, 5);}void Update(){transform.Translate(Vector3.forward * Time.deltaTime * moveSpeed);}
}
思考2 摄像机跟随效果

1、摄像机看向人物头顶上方一个位置(可调节)

2、摄像机在任务斜后方,通过角度控制斜率

3、通过鼠标滚轮可以控制摄像机与人物的距离(有最大最小限制)

4、Quaternion.Slerp实现摄像机看向人物

5、Vector3.Lerp实现相机跟随人物

using UnityEngine;public class CameraMovePlus : MonoBehaviour
{//摄像目标public Transform target;//头顶偏移位置public float overHeadOffset = 1;//倾斜角度public float tiltAngle = 45;//摄像机到头顶偏移位置的距离public float distance = 5;public float minDis = 3;public float maxDis = 8;public int scrollSpeed = 2;public int lookSpeed = 1;Vector3 nowPos;Vector3 nowDir;void Start(){//transform.rotation *= Quaternion.AngleAxis(45, Vector3.right);}void Update(){//3、通过鼠标滚轮可以控制摄像机与人物的距离(有最大最小限制)//滚轮distance += Input.GetAxis("Mouse ScrollWheel") * scrollSpeed;distance = Mathf.Clamp(distance, minDis, maxDis);//1、摄像机看向人物头顶上方一个位置(可调节)//偏移nowPos = target.position + target.up * overHeadOffset;//2、摄像机在任务斜后方,通过角度控制斜率nowDir = Quaternion.AngleAxis(tiltAngle, target.right) * -target.forward;nowPos = nowPos + nowDir * distance;//transform.position = nowPos;//Debug.DrawLine(transform.position, target.position + target.up * overHeadOffset);//摄像机方向//4、Quaternion.Slerp实现摄像机看向人物transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(-nowDir), Time.deltaTime * lookSpeed * 2);//5、Vector3.Lerp实现相机跟随人物transform.position = Vector3.Lerp(transform.position, nowPos, Time.deltaTime);}
}

相关文章:

1、Unity【基础】3D数学

3D数学 文章目录 3D数学1、数学计算公共类Mathf1、Mathf和Math2、区别3、Mathf中的常用方法&#xff08;一般计算一次&#xff09;4、Mathf中的常用方法&#xff08;一般不停计算&#xff09;练习 A物体跟随B物体移动 2、三角函数1、角度和弧度2、三角函数3、反三角函数练习 物…...

虚拟机ubuntu22的扩容记录

这里lsblk命令能看到&#xff0c; ubuntu逻辑分区只有29G&#xff0c; 但总分区60G&#xff0c;还有接近30G未使用。 rootx:/home/x# lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS loop0 7:0 0 63.9M 1 loop /snap/core2…...

Docker 常用配置

Docker 常用配置 1. 配置方法 修改下面位置&#xff1a; Linux&#xff1a;vim /etc/docker/daemon.jsonmacOS&#xff1a;菜单栏图标->Settings->Docker Engine 注意&#xff1a;修改完需要重启Docker Linux&#xff1a;systemctl restart dockermacOS&#xff1a;…...

通过示例了解 .NET Core 中的依赖注入

依赖注入 (DI) 是一种用于实现 IoC&#xff08;控制反转&#xff09;的设计模式&#xff0c;可以更好地解耦应用程序内的依赖关系并更轻松地管理它们。.NET Core 内置了对依赖注入的支持&#xff0c;提供了一种有效管理依赖关系的强大方法。 一.什么是依赖注入&#xff1f; 依…...

fetch、FormData上传多张图片

利用fetch方法和FormData对象上传多张图片 formdata()对象可以序列化多张图片 <html><head><meta http-equiv"content-type" content"text/html;charsetUTF-8"/><title>测试fetch和formdata上传多张图片</title></head&…...

C++STL详解(五)——list类的具体实现

一.本次所需实现的三个类及其成员函数接口 链表首先要有结点&#xff0c;因此我们需要实现一个结点类。 链表要有管理结点的结构&#xff0c;因此我们要有list类来管理结点。 链表中还要有迭代器&#xff0c;而迭代器的底层其实是指针。但是我们现有的结点类无法完成迭代器的…...

鸿蒙(API 12 Beta3版)【使用投播组件】案例应用

华为视频接入播控中心和投播能力概述** 华为视频在进入影片详情页播放时&#xff0c;支持在控制中心查看当前播放的视频信息&#xff0c;并进行快进、快退、拖动进度、播放暂停、下一集、调节音量等操作&#xff0c;方便用户通过控制中心来操作当前播放的视频。 当用户希望通…...

【STM32项目】在FreeRtos背景下的实战项目的实现过程(一)

个人主页~ 这篇文章是我亲身经历的&#xff0c;在做完一个项目之后总结的经验&#xff0c;虽然我没有将整个项目给放出来&#xff0c;因为这项目确实也是花了米让导师指导的&#xff0c;但是这个过程对于STM32的实战项目开发都是非常好用的&#xff0c;可以说按照这个过程&…...

C#垃圾处理机制相关笔记

C#编程中的垃圾处理机制主要通过垃圾回收器&#xff08;Garbage Collector&#xff0c;GC&#xff09;实现自动内存管理。C#作为一种托管语言&#xff0c;其垃圾处理机制显著减轻了程序员的内存管理负担&#xff0c;与C语言等非托管语言形成鲜明对比。具体介绍如下&#xff1a;…...

C语言memcmp函数

目录 开头1.什么是memcmp函数?2.memcmp函数的内部程序流程图 3.memcmp函数的实际应用比较整型数组比较短整型二维数组比较结构体变量…… 结尾 开头 大家好&#xff0c;我叫这是我58。今天&#xff0c;我们要学一下关于C语言里的memcmp函数的一些知识。 1.什么是memcmp函数?…...

低代码: 组件库测试之Vue环境下的测试工具以及测试环境搭建

Vue Test Utils Vue Test Utils 1 targets Vue 2. Vue Test Utils 2 targets Vue 3. 特别注意要使用 版本 2.0.0 以上 提供特定的方法,在隔离的话环境下,进行组件的挂载,以及一系列的测试 配置开发环境 手动配置, 是比较麻烦的vue cli 是基于插件架构的, 插件可以: 安装对…...

【Vue3】高颜值后台管理模板推荐

ELP - 权限管理系统 基于Vue 3框架与PrimeVue UI组件库技术精心构建的高颜值后台权限管理系统模板。该模板系统已成功实现基于RBAC&#xff08;Role-Based Access Control&#xff09;模型的权限管理系统和字典数据管理模块&#xff0c;后端则使用了Spring Boot框架&#xff0…...

详细介绍Pytorch中torchvision的相关使用

torchvision 是 PyTorch 的一个官方库&#xff0c;主要用于处理计算机视觉任务。提供了许多常用的数据集、模型架构、图像转换等功能&#xff0c;使得计算机视觉任务的开发变得更加高效和便捷。以下是对 torchvision 主要功能的详细介绍&#xff1a; 1. 数据集&#xff08;Dat…...

AI部署——主流模型推理部署框架

我们以最经典的Yolov5目标检测网络为例解释一下10种主流推理部署框架的大概内容&#xff0c;省略模型训练的过程&#xff0c;只讨论模型转换、环境配置、推理部署等步骤。 Intel的OpenVINO — CPUNvidia的TensorRT — GPU/CPUOpenCV DNN Module — GPU/CPUMicrosoft ONNX Runti…...

PyTorch之loading fbgemm.dll异常的解决办法

前言 PyTorch是一个深度学习框架&#xff0c;当我们在本地调试大模型时&#xff0c;可能会选用并安装它&#xff0c;目前已更新至2.4版本。 一、安装必备 1. window 学习或开发阶段&#xff0c;我们通常在window环境下进行&#xff0c;因此需满足以下条件&#xff1a; Windo…...

Vscode——如何实现 Ctrl+鼠标左键 跳转函数内部的方法

一、对于Python代码 安装python插件即可实现 二、对于C/C代码 安装C/C插件即可实现...

力扣热题100_回溯_78_子集

文章目录 题目链接解题思路解题代码 题目链接 78. 子集 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff…...

浏览器如何工作(一)进程架构

分享cosine 大佬&#xff0c;版权©️大佬所有 浏览器的核心功能 浏览器&#xff0c;“浏览” 是这个产品的核心&#xff0c;浏览无非分为两步&#xff1a; 获取想浏览的资源 展示得到的资源 现代浏览器还增加了交互功能&#xff0c;这涉及到脚本运行。因此&#xff0c…...

【LeetCode】两数之和

给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用两次相同的元素。 你可以按任意顺序返回答案。 示例 1…...

UE5学习笔记11-为拿取武器添加动画

一、一点说明 动画实例通过扩展为所有机器上的每个字符都存在动画蓝图&#xff0c;动画实例只能访问该计算机上的变量。 二、思路 我在武器组件中有一个武器类的指针&#xff0c;判断当前指针是否为空去判断当前角色是否装备武器 三、实现 1.在角色C类中添加是否装备武器的函…...

68. 文本左右对齐【 力扣(LeetCode) 】

一、题目描述 给定一个单词数组 words 和一个长度 maxWidth &#xff0c;重新排版单词&#xff0c;使其成为每行恰好有 maxWidth 个字符&#xff0c;且左右两端对齐的文本。 你应该使用 “贪心算法” 来放置给定的单词&#xff1b;也就是说&#xff0c;尽可能多地往每行中放置单…...

【中等】 猿人学web第一届 第6题 js混淆-回溯

文章目录 请求流程请求参数 加密参数定位r() 方法z() 方法 加密参数还原JJENCOde js代码加密环境检测_n("jsencrypt")12345 计算全部中奖的总金额请求代码注意 请求流程 请求参数 打开 调试工具&#xff0c;查看数据接口 https://match.yuanrenxue.cn/api/match/6 请…...

低、中、高频率段具体在不同应用中的范围是多少

1、低频率段&#xff08;Low Frequency Range&#xff09; ①建筑声学和噪声控制&#xff1a;通常将20 Hz 到 200 Hz 的频率范围视为低频段。在这一范围内&#xff0c;声音的波长较长&#xff0c;通常与低音&#xff08;如重低音音乐&#xff09;和建筑结构中的振动有关。 ②…...

Oxford Model600 Model400低温氦压缩机cryogenic helium compressor手侧

Oxford Model600 Model400低温氦压缩机cryogenic helium compressor手侧...

Golang面试题四(并发编程)

目录 1.Go常见的并发模型 2.哪些方法安全读写共享变量 3.如何排查数据竞争问题 ​4.Go有哪些同步原语 1. Mutex (互斥锁) 2. RWMutex (读写互斥锁) 3. Atomic 3.1.使用场景 3.2.整型操作 3.3.指针操作 3.4.使用示例 4. Channel 使用场景 使用示例 5. sync.WaitGr…...

计算机学生高效记录并整理编程学习笔记的方法

哪些知识点需要做笔记&#xff1f; 以下是我认为计算机学生大学四年可以积累的笔记。 ① 编程语言类&#xff08;C语言CJava&#xff09;&#xff1a;保留课堂笔记中可运行的代码部分&#xff0c;课后debug跑一跑。学习语言初期应该多写代码&#xff08;从仿写到自己写&#…...

【书生大模型实战】L2-LMDeploy 量化部署实践闯关任务

一、关卡任务 基础任务&#xff08;完成此任务即完成闯关&#xff09; 使用结合W4A16量化与kv cache量化的internlm2_5-7b-chat模型封装本地API并与大模型进行一次对话&#xff0c;作业截图需包括显存占用情况与大模型回复&#xff0c;参考4.1 API开发(优秀学员必做)使用Func…...

《编程学习笔记之道:构建知识宝库的秘诀》

在编程的浩瀚世界里&#xff0c;我们如同勇敢的探险家&#xff0c;不断追寻着知识的宝藏。而高效的笔记记录和整理方法&#xff0c;就像是我们手中的指南针&#xff0c;指引着我们在这片知识海洋中前行&#xff0c;不至于迷失方向。在这篇文章中&#xff0c;我们将深入探讨如何…...

DETR论文,基于transformer的目标检测网络 DETR:End-to-End Object Detection with Transformers

transformer的基本结构: encoder-decoder的基本流程为&#xff1a; 1&#xff09;对于输入&#xff0c;首先进行embedding操作&#xff0c;即将输入映射为向量的形式&#xff0c;包含两部分操作&#xff0c;第一部分是input embedding&#xff1a;例如&#xff0c;在NLP领域&…...

untiy有渲染线程和逻辑线程嘛

之前我也这么认为&#xff0c;其实unity引擎是单线程的&#xff0c;当然后续的jobs不在考虑范围内 如果你在一个awake 或者 start方法中 延时&#xff0c;是会卡住主线程的 比如 其实游戏引擎有一个基础简单理解&#xff0c;那就是不断的进行一个循环&#xff0c;在这个周期循…...

省建设厅网站梁作庆/百度云搜索

是因为ID类型不对的缘故。 我这是因为传的是一个string类型的。...

网站上的qq如何做悬浮/2022十大网络营销案例

射人先射马&#xff0c;擒贼先擒王 在我们学习sonic的过程中&#xff0c;无疑了解sonic的架构是非常重要的&#xff0c;然后再去了解各个模块的细节&#xff0c;总分学习模式。下面是我自我学习并翻译的链接https://github.com/Azure/SONiC/wiki/Architecture?spma2c6h.128736…...

建立网站的步骤和费用/好用搜索引擎排名

同义词用于提高搜索质量并扩大匹配范围。 例如&#xff0c;搜索 England 的用户可能希望找到包含 British 或 UK 的文档&#xff0c;尽管这三个词完全不同。 Elasticsearch 中的同义词功能非常强大&#xff0c;如果实施得当&#xff0c;可以使你的搜索引擎更加健壮和强大。 在…...

做网站实训报告/茂名网站建设制作

文章发自http://www.cnblogs.com/hark0623/p/4167363.html 转发请注明 注意&#xff1a;基于CDH进行Spark开发时&#xff0c;使用高版本的apache原生包即可&#xff1b;不需要使用CDH中的spark开发包&#xff0c;不然会死都不知道死的。另外&#xff0c;其它生态项目也如此。 补…...

武汉网站设计武/石家庄最新消息

Java 是当今最流行的编程语言之一&#xff0c;常年位居最受欢迎编程语言排行榜前三。一个优秀的java程序员&#xff0c;在研发时离不开对测试框架的了解&#xff0c;从而开发出更安全和更高效的代码。使用这些测试框架的其中一个最重要的原因是减少出错的可能性&#xff0c;提高…...

盐城建设银行招聘网站/网站seo分析报告

title: AWS之Qwiklab subtitle: 4. Qwiklab实验-Amazon DynamoDB, Amazon Redshift, Elasticsearch Service date: 2018-09-22 12:29:20 --- Introduction to Amazon DynamoDB Amazon DynamoDB简介 知识梳理 1. 定义与作用 首先&#xff0c;Amazon DynamoDB是非关系型数据库&am…...