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中的常用方法(一般计算一次)4、Mathf中的常用方法(一般不停计算)练习 A物体跟随B物体移动 2、三角函数1、角度和弧度2、三角函数3、反三角函数练习 物…...
虚拟机ubuntu22的扩容记录
这里lsblk命令能看到, ubuntu逻辑分区只有29G, 但总分区60G,还有接近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. 配置方法 修改下面位置: Linux:vim /etc/docker/daemon.jsonmacOS:菜单栏图标->Settings->Docker Engine 注意:修改完需要重启Docker Linux:systemctl restart dockermacOS:…...
通过示例了解 .NET Core 中的依赖注入
依赖注入 (DI) 是一种用于实现 IoC(控制反转)的设计模式,可以更好地解耦应用程序内的依赖关系并更轻松地管理它们。.NET Core 内置了对依赖注入的支持,提供了一种有效管理依赖关系的强大方法。 一.什么是依赖注入? 依…...
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类的具体实现
一.本次所需实现的三个类及其成员函数接口 链表首先要有结点,因此我们需要实现一个结点类。 链表要有管理结点的结构,因此我们要有list类来管理结点。 链表中还要有迭代器,而迭代器的底层其实是指针。但是我们现有的结点类无法完成迭代器的…...
鸿蒙(API 12 Beta3版)【使用投播组件】案例应用
华为视频接入播控中心和投播能力概述** 华为视频在进入影片详情页播放时,支持在控制中心查看当前播放的视频信息,并进行快进、快退、拖动进度、播放暂停、下一集、调节音量等操作,方便用户通过控制中心来操作当前播放的视频。 当用户希望通…...
【STM32项目】在FreeRtos背景下的实战项目的实现过程(一)
个人主页~ 这篇文章是我亲身经历的,在做完一个项目之后总结的经验,虽然我没有将整个项目给放出来,因为这项目确实也是花了米让导师指导的,但是这个过程对于STM32的实战项目开发都是非常好用的,可以说按照这个过程&…...
C#垃圾处理机制相关笔记
C#编程中的垃圾处理机制主要通过垃圾回收器(Garbage Collector,GC)实现自动内存管理。C#作为一种托管语言,其垃圾处理机制显著减轻了程序员的内存管理负担,与C语言等非托管语言形成鲜明对比。具体介绍如下:…...
C语言memcmp函数
目录 开头1.什么是memcmp函数?2.memcmp函数的内部程序流程图 3.memcmp函数的实际应用比较整型数组比较短整型二维数组比较结构体变量…… 结尾 开头 大家好,我叫这是我58。今天,我们要学一下关于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(Role-Based Access Control)模型的权限管理系统和字典数据管理模块,后端则使用了Spring Boot框架࿰…...
详细介绍Pytorch中torchvision的相关使用
torchvision 是 PyTorch 的一个官方库,主要用于处理计算机视觉任务。提供了许多常用的数据集、模型架构、图像转换等功能,使得计算机视觉任务的开发变得更加高效和便捷。以下是对 torchvision 主要功能的详细介绍: 1. 数据集(Dat…...
AI部署——主流模型推理部署框架
我们以最经典的Yolov5目标检测网络为例解释一下10种主流推理部署框架的大概内容,省略模型训练的过程,只讨论模型转换、环境配置、推理部署等步骤。 Intel的OpenVINO — CPUNvidia的TensorRT — GPU/CPUOpenCV DNN Module — GPU/CPUMicrosoft ONNX Runti…...
PyTorch之loading fbgemm.dll异常的解决办法
前言 PyTorch是一个深度学习框架,当我们在本地调试大模型时,可能会选用并安装它,目前已更新至2.4版本。 一、安装必备 1. window 学习或开发阶段,我们通常在window环境下进行,因此需满足以下条件: Windo…...
Vscode——如何实现 Ctrl+鼠标左键 跳转函数内部的方法
一、对于Python代码 安装python插件即可实现 二、对于C/C代码 安装C/C插件即可实现...
力扣热题100_回溯_78_子集
文章目录 题目链接解题思路解题代码 题目链接 78. 子集 给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1: 输入ÿ…...
浏览器如何工作(一)进程架构
分享cosine 大佬,版权©️大佬所有 浏览器的核心功能 浏览器,“浏览” 是这个产品的核心,浏览无非分为两步: 获取想浏览的资源 展示得到的资源 现代浏览器还增加了交互功能,这涉及到脚本运行。因此,…...
【LeetCode】两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。 你可以按任意顺序返回答案。 示例 1…...
UE5学习笔记11-为拿取武器添加动画
一、一点说明 动画实例通过扩展为所有机器上的每个字符都存在动画蓝图,动画实例只能访问该计算机上的变量。 二、思路 我在武器组件中有一个武器类的指针,判断当前指针是否为空去判断当前角色是否装备武器 三、实现 1.在角色C类中添加是否装备武器的函…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)
1.获取 authorizationCode: 2.利用 authorizationCode 获取 accessToken:文档中心 3.获取手机:文档中心 4.获取昵称头像:文档中心 首先创建 request 若要获取手机号,scope必填 phone,permissions 必填 …...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
基于Java+MySQL实现(GUI)客户管理系统
客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息,对客户进行统一管理,可以把所有客户信息录入系统,进行维护和统计功能。可通过文件的方式保存相关录入数据,对…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...
