3D数学
文章目录
- 3D数学
-
- 1、数学计算公共类Mathf
-
- 1、Mathf和Math
- 2、区别
- 3、Mathf中的常用方法(一般计算一次)
- 4、Mathf中的常用方法(一般不停计算)
- [练习 A物体跟随B物体移动](#练习 A物体跟随B物体移动)
- 2、三角函数
- 3、Unity中的坐标系
- 4、Vector3向量
- 5、Quaternion四元数
3D数学
1、数学计算公共类Mathf
1、Mathf和Math
c
Math是c#中封装好的用于【数学计算的工具类】位于system命名空间中
public static class Math{}
Mathf是Unity中封装好的用于【数学计算的工具结构体】位于UnityEngine命名空间中
public struct Mathf{}
他们都是提供来用于进行【数学相关计算】的
2、区别
c
一个是静态类,一个是结构体
Mathf比Math有更多的数学计算方法
3、Mathf中的常用方法(一般计算一次)
csharp
void Start()
{
1、π PI
Mathf.PI
2、绝对值 Abs
3、向上取整 CeilToInt
print(Mathf.CeilToInt(1.3f)); //2
4、向下取整 FloorToInt
5、钳制函数 Clamp (在参数二,和参数三的范围里取值)
print(Mathf.Clamp(10, 11, 22)); //11
print(Mathf.Clamp(23, 11, 22)); //22
print(Mathf.Clamp(16, 11, 22)); //16
6、获取最大值 Max
7、获取最小值 Min
8、一个数的n次方 Pow
print(Mathf.Pow(2, 3)); //2的3次方
9、四舍五入 RoundToInt
10、返回一个数的平方根 Sqrt
11、判断一个数是否是2的n次方 IsPowerOfTwo
print(Mathf.IsPowerOfTwo(1)); //true
12、判断正负数 Sign
print(Mathf.Sign(8)); //1
print(Mathf.Sign(-8)); //-1
}
4、Mathf中的常用方法(一般不停计算)
csharp
float start = 0;
float result = 0;
float time = 0;
void Update()
{
插值运算 Lerp
Lerp函数公式
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物体移动
csharp
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、角度和弧度
csharp
1.角度和弧度
角度:1°
弧度:1 (radian)
圆一周的弧度:2π (radian)
2.角度和弧度的关系
π rad = 180°
则:
1 rad ≈ 57.3°
1° ≈ 0.01745 rad
角度 = 弧度 * 57.3
float rad = 1;
float angle = rad * Mathf.Rad2Deg;
弧度 = 角度 * 0.01745
angle = 1;
rad = angle * Mathf.Deg2Rad;
2、三角函数
csharp
Mathf中,只使用弧度,所以要角度转弧度(Deg2Rad)
sin30°
Mathf.Sin(30 * Mathf.Deg2Rad);
3、反三角函数
c
通过反三角函数计算正弦值或余弦值对应的弧度值
弧度 = Mathf.Asin(正弦值)
弧度 = Mathf.Acos(余弦值)
float radian = Mathf.Asin(0.5f); //先将值转化为弧度
float degree = radian * Mathf.Rad2Deg; //再将弧度转角度
print(degree);
练习 物体曲线移动
csharp
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、世界坐标系
c
原点:世界的中心点
轴向:世界坐标系的三个轴向是固定的
transform.position;
transform.rotation;
transform.eulerAngles; //欧拉角
transform.lossyScale; //缩放
2、物体坐标系
c
原点:物体的中心点(建模时决定)
轴向:
物体的方右为x轴正方向
物体的上方为y轴正方向
物体的前方为z轴正方向
//相对父对象的坐标
transform.localPosition;
transform.localRotation;
transform.localEulerAngles;
transform.localScale;
3、屏幕坐标系
c
原点:屏幕左下角
轴向:
向右为x轴正方向
向上为y轴正方向
最大宽高:
Input.mousePosition;
Screen.width;
Screen.height;
4、视口坐标系
c
原点:屏幕左下角
轴向:
向右为x轴正方向
向上为y轴正方向
特点:
左下角(0,0)
右上角(1,1)
和屏幕坐标类似,将坐标单位化
摄像机上的【视口范围】属于视口 Viewport Rect
5、坐标转换
c
世界转本地
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、向量基础
c
三维向量 Vector3
Vector3有两种意义:
1、可以表示位置 代表一个点
transform.position;
2、也可以表示方向 代表一个方向
transform.forward;
2、两点决定 向量
csharp
Vector3 A = new Vector3(1, 2, 3);
Vector3 B = new Vector3(2, 3, 4);
求向量 终点 - 起点
Vector3 AB = B - A;
Vector3 BA = A - B;
3、零向量和负向量
c
零向量
(0,0,0)
Vector3.zero;
负向量
(x,y,z)的负向量为(-x,-y,-z)
Vector3.forward;
-Vector3.forward;
4、向量模长
c
模长:向量的长度
AB.magnitude; //AB的模长
Vector3 C = new Vector3(3, 4, 5);
print(C.magnitude); //点C到原点的模长
Vector3.Distance(A, B); //两点之间的距离
5、单位向量
c
模长为1的向量
只管方向
AB.normalized;
AB / AB.magnitude;
2、向量加减乘除
c
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只能得,不能改
练习:向量实现摄像机跟随
csharp
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、点乘的计算
c
向量A(Xa,Ya,Za)
向量B(Xb,Yb,Zb)
A*B = Xa*Xb + Ya*Yb + Za*Zb
向量 * 向量 = 标量
2、点乘的几何意义
c
点乘可以得到向量的投影长度
点乘结果>0,两个向量的夹角为锐角 (目标在前)
点乘结果=0,两个向量的夹角为直角 (目标在左or右两侧不确定)
点乘结果<0,两个向量的夹角为钝角 (目标在后)
作用:判断目标的大致方位
unity点乘
csharp
调试画线
//线段 参数(起点,终点)
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、公式推导
c
已知单位模长A 单位模长B,以及点乘的几何意义;
则:
cosβ = 单位向量A * 单位向量B
再根据数学的反三角函数推出:
β = Mathf.Acos(A*B) * Mathf.Rad2Deg
4、通过点乘推导公式算出夹角
csharp
//单位向量算出点乘结果(方向向量)
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°的扇形区域
csharp
方法一:
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 + "米");
}
}
}
csharp
方法二: 用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、叉乘计算公式
c
向量 * 向量 = 向量
向量A(Xa,Ya,Za)
向量B(Xb,Yb,Zb)
A*B=(X,Y,Z)
X = Ya*Zb - Za*Yb
Y = Za*Xb - Xa*Zb
Z = Xa*Yb - Ya*Xb
Vector3.Cross();
2、几何意义
c
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的左侧");
}
练习 物体方位
csharp
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、线性插值
c
Vector3.Lerp(start, end, t);
对两个点进行插值计算
t的取值范围为0~1
计算公式:result = start + (end - start) * t
应用
1、每帧改变start的值(先快后慢)
2、每帧改变t的值(匀速)
两种线性插值代码实现
csharp
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、球性插值
csharp
Vector3.slerp(start, end, t);
对两个向量进行插值运算 t:(0~1)
//运动轨迹为弧形
C.position = Vector3.Slerp(transform.forward * 10, -transform.forward * 3, time);
思考1 Lerp摄像机跟随
csharp
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);
}
csharp
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 球形插值模拟太阳升降
csharp
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、为何使用四元数
csharp
Rotation表示欧拉角 transform.eulerAngles
因为欧拉角存在一些缺点:
1、同一旋转的表示不唯一
2、万向节死锁
而四元数旋转不存在万向节死锁问题
所以使用四元数来表示三维空间中的旋转信息
2、四元数是什么
1、四元数的构成
csharp
四元数包含一个标量和一个3D向量
[w,v] w为标量,v为3D向量
[w,(x,y,z)]
四元数表示3D空间中的一个旋转量
轴-角对(含义):
绕一个轴(Q)旋转β度
2、Unity中的四元数
c
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、四元数和欧拉角转换
csharp
1、欧拉角转四元数
Quaternion q = Quaternion.Euler(60,0,0);
2、四元数转欧拉角
q.eulerAngles;
4、四元数弥补欧拉角的缺点
csharp
四元数相乘:旋转四元数
1、四元数的结果始终是 -180~180
2、四元数旋转可以避免万向节死锁
3、四元数常用方法
1、单位四元数
c
没有旋转量(角位移)
Unity:
Quaternion.identity
例:
[1,(0,0,0)]
[-1,(0,0,0)]
作用:
对象角度初始化
2、插值运算
csharp
// 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、向量方向 转换为对应 四元数角度
csharp
API:Quaternion.LookRotation(目标向量)
public Transform LA;
public Transform LB;
void Update()
{
LA.rotation = Quaternion.LookRotation(LB.position - LA.position);
}
思考1 写一个类似LookAt()的拓展方法
csharp
public static class Tool
{
public static void MyLookAt(this Transform obj,Transform target)
{
obj.rotation = Quaternion.LookRotation(target.position - obj.position);
}
}
思考2 用LookRotation实现摄像机跟随
csharp
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、四元数相乘
csharp
q1 = q2 * q3
两个旋转量的叠加
旋转方向一直是本地坐标系
Quaternion qua = Quaternion.AngleAxis(30, Vector3.up);
transform.rotation *= qua; //沿y轴顺时针旋转30度
transform.rotation *= qua; //再旋转30度
2、四元数乘向量
csharp
V1 = v2 * q
旋转【四元数角度】向量
Vector3 v = Vector3.forward;
v = Quaternion.AngleAxis(45, Vector3.up) * v; //此处必须:先四元数,再乘向量
思考1 模拟飞机发射子弹,单发、双发、扇形、环形
AirPlane 飞机类
csharp
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 子弹类
csharp
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实现相机跟随人物
csharp
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);
}
}