向量相减,向量相加
如上图a-b为c, a+b为d —> 在unity中相加相减后向量起点为加减向量公共起点
向量与数的乘与除 —> 模长的缩放
向量与向量的乘与除 —>1.点乘Dot:[x1,y1,z1][x1,y2,z2] = x1x2+y1y2+z1x2
参与点乘运算的向量标准化后,结果为夹角的 cos 值,几何意义Dot(a,b) = |a||b|*cos(a,b),只能看[0,180]之间,不能看出顺/逆时针,顺/逆时针须用叉乘
2.叉乘Cross:两个矢量的叉积产生第三矢量,该矢量垂直于两个输入矢量。结果的幅度等于两个输入的幅度相乘,然后乘以输入之间角度的正弦值。您可以使用“左手规则”确定结果向量的方向。
//计算向量长度
Vector3 pos = transform.position;
float m2 = pos.magnitude;
//计算向量方向(单位向量)
Vector3 pos = transform.position;
Vector3 n1 = pos / pos.magnitude; //自己计算:向量/模场
Vector3 n2 = pos.normalized; // normalized属性为单位向量
public float angle;
//向量
private void Demo08()
{
//向量 + - 向量
//向量 * / 数
//向量 (点乘Dot) (叉乘Cross) 向量
//
//参与点乘运算的向量标准化后,结果为夹角的 cos 值
float dot = Vector3.Dot(t1.position.normalized, t2.position.normalized);
angle = Mathf.Acos(dot) * Mathf.Rad2Deg;
//if (angle > 30)//比较角度
if (dot < 0.866f)//比较cos值
{
//如果夹角大于30度则
}
Vector3 cross = Vector3.Cross(t1.position, t2.position);
if (cross.y <0) //cross的y小于0则角度为逆时针,否则为顺时针
{
angle = 360 - angle;
}
}
弧度与角度
private void Demo04()
{
// f1角度=>f2 弧度: 弧度=角度数*PI/180
float f1 = 50;
float f2 = f1 * Mathf.PI / 180;
float f3 = f1 * Mathf.Deg2Rad;
// Mathf.Rad2Deg 弧度 ---> 角度
//Mathf.Deg2Rad 角度 ---> 弧度
}
三角函数:根据一边一角求另一边
Mathf.Sin(x * Mathf.Deg2Rad) 输入弧度返回sin的值范围[-1,1]
Mathf.Cos(x * Mathf.Deg2Rad)
Mathf.Tan(x * Mathf.Deg2Rad)
反三角函数:根据两边求角
Mathf.Asin(0.5f) 输入浮点数值返回值对应的sin角度
Mathf.Acos(0.5f )
Mathf.Atan(0.5f)
三角/反三角函数例子:
//已知:角度x 边长 a
//计算:边长 c
float x = 50;
float a = 10;
float c = a / Mathf.Sin(x * Mathf.Deg2Rad);
//已知:边长 a c
//计算:角度angle
float angle = Mathf.Asin(a / c) * Mathf.Rad2Deg;
自身坐标 —> 世界坐标
private void Demo06()
{
//返回自身坐标系前方10m的世界坐标系
Vector3 worldPos = transform.TransformPoint(0, 0, 10);
Debug.DrawLine(this.transform.position, worldPos);
}
//练习计算:前右方30度 10米处世界坐标
private void Demo07()
{
Vector3 localPos = new Vector3
(
10 * Mathf.Sin(30 * Mathf.Deg2Rad),
0,
10 * Mathf.Cos(30 * Mathf.Deg2Rad)
);
Vector3 worldPos = transform.TransformPoint(localPos);
Debug.DrawLine(transform.position, worldPos);
}
向量Vector的API
//因为 position 是属性,所以返回数据副本,直接修改z无效。所以编译错误。
//transform.position.z = 1;
//方案1:
//复制(数据)
Vector3 pos = transform.position;
pos.z = 1;//如果仅仅修改位置的副本,物体位置不会发生改变
transform.position = pos;
//方案2:
transform.position = new Vector3(transform.position.x, transform.position.y, 1);
//Vector3.Distance(位置1,位置2) 实际调用(位置1 - 位置2).模长
//建议 (位置1 - 位置2).模长平方 sqrMagnitude
Vector3 norm = t1.position;
计算垂直向量
//Vector3.OrthoNormalize(ref norm, ref tangent, ref binNormal);
//计算t1物体在地面上的投影
Vector3 project = Vector3.ProjectOnPlane(norm, Vector3.up);
Debug.DrawLine(Vector3.zero, norm);
Debug.DrawLine(Vector3.zero, project,Color.red);
//计算反射向量:Vector3.Reflect
//移动类API
//由快到慢 无限接近目标点
//起点改变 终点、比例不变
transform.position =Vector3.Lerp(transform.position, new Vector3(0, 0, 10), 0.1f);
//匀速移动 无限接近目标点
transform.position =Vector3.MoveTowards(transform.position, new Vector3(0, 0, 10), 0.1f);
//平滑阻尼
transform.position =Vector3.SmoothDamp(transform.position, new Vector3(0, 0, 10), ref currentSpeed, 2);
//变速运动
public AnimationCurve curve //曲线编辑器
x += Time.deltaTime / time; //time=1 1S到终点 2 2s到终点
//由快到慢 无限接近目标点
//起点 、终点 不变 比例改变
Vector3 begin = Vector3.zero;
//transform.position =
// Vector3.Lerp(begin, new Vector3(0, 0, 10), curve.Evaluate(x)); //限制y超过
transform.position =
Vector3.LerpUnclamped(begin, new Vector3(0, 0, 10), curve.Evaluate(x));//不限制y超过
欧拉角:
x,z绕自身坐标系旋转,y绕世界坐标系y轴旋转
当延x轴旋转90°时,自身z与世界y重合,会造成万向节死锁.
transform.eulerAngles = new Vector3(10, 10, 0); //赋值
transform.eulerAngles += new Vector3(1, 0, 0); //绕x轴转
transform.eulerAngles += Vector3.up; //绕y轴
transform.eulerAngles += Vector3.forward; //绕z轴
四元数:
四元数用于表示旋转。
它们结构紧凑,不受万向节锁定的影响,。Unity内部使用四元数来表示所有旋转.
四元数旋转均延自身旋转
四元数的表示
//物体沿Y轴旋转50度
Vector3 axis = Vector3.up;
float rad = 50 * Mathf.Deg2Rad;
Quaternion qt = new Quaternion();
qt.x = Mathf.Sin(rad / 2) * axis.x;
qt.y = Mathf.Sin(rad / 2) * axis.y;
qt.z = Mathf.Sin(rad / 2) * axis.z;
qt.w = Mathf.Cos(rad / 2);
transform.rotation = qt;
//等同于调用Quaternion.Euler(0, 50, 0)
transform.rotation = Quaternion.Euler(0, 50, 0);
transform.rotation *= Quaternion.Euler(1, 0, 0); //沿X轴旋转
//transform.Rotate(1, 0, 0); //Rotate通过四元数实现
transform.rotation *= Quaternion.Euler(0, 1, 0); //沿Y轴旋转
transform.rotation *= Quaternion.Euler(0, 0, 1); //沿Z轴旋转
四元数与向量相乘
四元数左乘向量:表示将该向量旋转四元数对应的角度
两个四元数与向量累乘:将向量连续旋转
//计算物体右前方30度10m处坐标
Vector3 worldPos =
transform.position + Quaternion.Euler(0, 30, 0) * transform.rotation * new Vector3(0, 0, 10);
四元数Quaternion的API
//获取四元数
Quaternion qt = transform.rotation;
//1. 四元数 --> 欧拉角
Vector3 euler = qt.eulerAngles;
//2.欧拉角 --> 四元数
Quaternion qt02 = Quaternion.Euler(0, 90, 0);
//3.轴 / 角 旋转
//transform.rotation = Quaternion.AngleAxis(30, Vector3.up);
//transform.localRotation = Quaternion.AngleAxis(30, Vector3.up);
//4. 注视旋转
//Quaternion dir = Quaternion.LookRotation(target.position - transform.position);
//transform.rotation = dir;
//transform.LookAt(target.position);
//5.Lerp 插值旋转 由快到慢
//transform.rotation = Quaternion.Lerp(transform.rotation, dir, 0.1f);
//6.RotateTowards 匀速旋转
//transform.rotation = Quaternion.RotateTowards(transform.rotation, dir, 0.1f);
//Quaternion dir = Quaternion.Euler(0, 180, 0);
//transform.rotation = Quaternion.Lerp(transform.rotation, dir, 0.005f);
7. 四元数计算角度差
//if (Quaternion.Angle(transform.rotation, dir) < 30)
// transform.rotation = dir;
//8. X轴注视旋转
transform.rotation = Quaternion.FromToRotation(Vector3.right, target.position - transform.position);
切点探测
GameObject playerGO = GameObject.FindWithTag("Player");
playerTF = playerGO.transform;
radius = playerGO.GetComponent<CapsuleCollider>().radius;
public void CalaculateTangent()
{
Vector3 playerToExplosion = transform.position - playerTF.position;
Vector3 playerToExplosionRadius = playerToExplosion.normalized * radius;
float angle = Mathf.Acos(radius / playerToExplosion.magnitude) * Mathf.Rad2Deg;
rightTangent =playerTF .position + Quaternion.Euler(0, angle, 0) * playerToExplosionRadius;
leftTangent = playerTF.position + Quaternion.Euler(0, -angle, 0) * playerToExplosionRadius;
}
//**************测试**************
private void Update()
{
CalaculateTangent();
Debug.DrawLine(transform.position, leftTangent);
Debug.DrawLine(transform.position, rightTangent);