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类中添加是否装备武器的函…...
68. 文本左右对齐【 力扣(LeetCode) 】
一、题目描述 给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。 你应该使用 “贪心算法” 来放置给定的单词;也就是说,尽可能多地往每行中放置单…...
【中等】 猿人学web第一届 第6题 js混淆-回溯
文章目录 请求流程请求参数 加密参数定位r() 方法z() 方法 加密参数还原JJENCOde js代码加密环境检测_n("jsencrypt")12345 计算全部中奖的总金额请求代码注意 请求流程 请求参数 打开 调试工具,查看数据接口 https://match.yuanrenxue.cn/api/match/6 请…...
低、中、高频率段具体在不同应用中的范围是多少
1、低频率段(Low Frequency Range) ①建筑声学和噪声控制:通常将20 Hz 到 200 Hz 的频率范围视为低频段。在这一范围内,声音的波长较长,通常与低音(如重低音音乐)和建筑结构中的振动有关。 ②…...
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…...
计算机学生高效记录并整理编程学习笔记的方法
哪些知识点需要做笔记? 以下是我认为计算机学生大学四年可以积累的笔记。 ① 编程语言类(C语言CJava):保留课堂笔记中可运行的代码部分,课后debug跑一跑。学习语言初期应该多写代码(从仿写到自己写&#…...
【书生大模型实战】L2-LMDeploy 量化部署实践闯关任务
一、关卡任务 基础任务(完成此任务即完成闯关) 使用结合W4A16量化与kv cache量化的internlm2_5-7b-chat模型封装本地API并与大模型进行一次对话,作业截图需包括显存占用情况与大模型回复,参考4.1 API开发(优秀学员必做)使用Func…...
《编程学习笔记之道:构建知识宝库的秘诀》
在编程的浩瀚世界里,我们如同勇敢的探险家,不断追寻着知识的宝藏。而高效的笔记记录和整理方法,就像是我们手中的指南针,指引着我们在这片知识海洋中前行,不至于迷失方向。在这篇文章中,我们将深入探讨如何…...
DETR论文,基于transformer的目标检测网络 DETR:End-to-End Object Detection with Transformers
transformer的基本结构: encoder-decoder的基本流程为: 1)对于输入,首先进行embedding操作,即将输入映射为向量的形式,包含两部分操作,第一部分是input embedding:例如,在NLP领域&…...
untiy有渲染线程和逻辑线程嘛
之前我也这么认为,其实unity引擎是单线程的,当然后续的jobs不在考虑范围内 如果你在一个awake 或者 start方法中 延时,是会卡住主线程的 比如 其实游戏引擎有一个基础简单理解,那就是不断的进行一个循环,在这个周期循…...
省建设厅网站梁作庆/百度云搜索
是因为ID类型不对的缘故。 我这是因为传的是一个string类型的。...
网站上的qq如何做悬浮/2022十大网络营销案例
射人先射马,擒贼先擒王 在我们学习sonic的过程中,无疑了解sonic的架构是非常重要的,然后再去了解各个模块的细节,总分学习模式。下面是我自我学习并翻译的链接https://github.com/Azure/SONiC/wiki/Architecture?spma2c6h.128736…...
建立网站的步骤和费用/好用搜索引擎排名
同义词用于提高搜索质量并扩大匹配范围。 例如,搜索 England 的用户可能希望找到包含 British 或 UK 的文档,尽管这三个词完全不同。 Elasticsearch 中的同义词功能非常强大,如果实施得当,可以使你的搜索引擎更加健壮和强大。 在…...
做网站实训报告/茂名网站建设制作
文章发自http://www.cnblogs.com/hark0623/p/4167363.html 转发请注明 注意:基于CDH进行Spark开发时,使用高版本的apache原生包即可;不需要使用CDH中的spark开发包,不然会死都不知道死的。另外,其它生态项目也如此。 补…...
武汉网站设计武/石家庄最新消息
Java 是当今最流行的编程语言之一,常年位居最受欢迎编程语言排行榜前三。一个优秀的java程序员,在研发时离不开对测试框架的了解,从而开发出更安全和更高效的代码。使用这些测试框架的其中一个最重要的原因是减少出错的可能性,提高…...
盐城建设银行招聘网站/网站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. 定义与作用 首先,Amazon DynamoDB是非关系型数据库&am…...