向量和四元数练习
void Start()
{
Vector3 A = new Vector3(1, 2, 3);
Vector3 B = new Vector3(4, 5, 6);
//1.向量的模长 就是 两个点之间的距离
Vector3 AB = B - A;//终点 - 起点
//通过向量得到长度
print(AB.magnitude);
//通过API得到长度
print(Vector3.Distance(A,B));
//2.单位向量 就是 只需要方向 不需要模长
print(AB.normalized);
//3.向量模长的计算 根号下每个数的平方相加
//4.单位向量的计算 先计算出模长 在分别除以向量
//摄像机跟随
//写在LateUpdate中
//void LateUpdate()
//{
// //摄像机的位置 = 目标位置 + 偏移
// this.transform.position = cubeTrans.position + cubeTrans.forward * 5 + cubeTrans.up * 10;
// this.transform.LookAt(cubeTrans);
//}
//向量点乘
//1.假设有一个物体 不确定他在我的前面还是后面 就可以通过向量点乘的方式来判断
//通过正前方的向量 * 向量(目标位置 - 我的位置 得到向量)判断这个角度是否大于等于90°就在前面 小于就在后面
float f = Vector3.Dot(this.transform.forward, trans.position - this.transform.position);
//2.通过公式推导计算出夹角
//*****************************
//使用API
float f1 = Vector3.Angle(this.trans.forward, trans.position - this.transform.position);
/*void Update()
{
//画一条射线
//第一个参数是起始位置
//第二个参数是方向
Debug.DrawRay(this.transform.position,trans.position - this.transform.position,Color.blue);
//小练习
float f1 = Vector3.Angle(this.trans.forward, trans.position - this.transform.position);
if (f1 <= 22.5f && Vector3.Distance(this.trans.position,this.transform.position) <= 5)
{
Debug.Log("123");
}
}
*/
//向量叉乘
//传入的值都代表向量
Vector3 v = Vector3.Cross(A.position, B.position);
if(v.y > 0)
{
Debug.Log("B在A的右侧");
}
else
{
Debug.Log("B在A的左侧");
}
//叉乘的几何意义
//点乘只能判断一个物体在某个角度范围内 但不能确定左右
//叉乘会根据Y值判断出一个物体的左右
}
//小练习 判断一个物体在哪里
Debug.DrawRay(this.A.position, this.B.position - this.A.position, Color.green);
//点乘 前方向量 * 向量
float f1 = Vector3.Dot(A.forward, B.position - A.position);
//叉乘 法向量
Vector3 v1 = Vector3.Cross(A.forward, B.position - A.position);
//后面的 判断前面的
//点乘大于0 说明在前面
if (f1 >= 0)
{
//叉乘的y大于0 说明在右边
if (v1.y >= 0)
{
Debug.Log("B在A的右前");
}
//小于0 在左边
else
{
Debug.Log("B在A的左前");
}
}
//叉乘小于0 说明在后面
else
{
//叉乘的y大于0 说明在右边
if (v1.y >= 0)
{
Debug.Log("B在A的右后");
}
else
{
Debug.Log("B在A的左后");
}
}
//计算角度
float f2 = Vector3.Angle(A.forward, B.position - A.position);
//可以根据角度判断物体小于or大于多少度
//向量插值运算
//插值
//start是起始位置 end是终止位置 time是0-1取值
//计算公式 = start + (end - start)* t
//先快后慢 无限趋近于end 但不会等于end
float start = Vector3.Lerp(start,end,Time.deltatime);
//匀速
//start是恒定不动的 所以是匀速的
time += Time.deltatime;
float result = Vector3.Lerp(start,end,nowTime);
//球形插值
Vector3.Slerp(start, end, time);
//四元数
//轴 角对
Quaternion q = Quaternion.AngleAxis(1, Vector3.up);
//四元数解决欧拉角1.同一角度表示不唯一 2.万向节死锁问题
//四元数只会表示180 - 负180
//四元数相乘表示旋转
//单位四元数
this.transform.rotation = Quaternion.identity;
//LookRotation(传入一个方向向量)
Quaternion.LookRotation(target.postion - this.transform.position);
//小练习 假设Transform没有LookAt方法 利用四元数的LookRotation方法实现该方法
public static class 基础
{
//C#拓展方法的练习 首先类是静态的 函数也是静态的
//第一个参数就是调用者本身 第二个参数是目标值
public static void MyLookAt(this Transform obj,Transform target)
{
Quaternion q = Quaternion.LookRotation(target.position - obj.position);
obj.transform.rotation = q;
}
}
四元数小练习
//飞机四种发射子弹的方式 分别是单发 双发 扇形 四周发射
public enum E_TypeFire
{
One,
Two,
Three,
Four
}
public class 基础 : MonoBehaviour
{
public E_TypeFire type = E_TypeFire.One;
public GameObject bullet;
public int num = 4;
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha0))
{
type = E_TypeFire.One;
}
else if (Input.GetKeyDown(KeyCode.Alpha1))
{
type = E_TypeFire.Two;
}
else if (Input.GetKeyDown(KeyCode.Alpha2))
{
type = E_TypeFire.Three;
}
else if (Input.GetKeyDown(KeyCode.Alpha3))
{
type = E_TypeFire.Four;
}
if(Input.GetKeyDown(KeyCode.Space))
{
Fire();
}
}
public void Fire()
{
switch(type)
{
case E_TypeFire.One:
Instantiate(bullet, this.transform.position, this.transform.rotation);
break;
case E_TypeFire.Two:
Instantiate(bullet,this.transform.position + this.transform.right * 0.5f , this.transform.rotation);
Instantiate(bullet,this.transform.position - this.transform.right * 0.5f , this.transform.rotation);
break;
case E_TypeFire.Three:
Instantiate(bullet, this.transform.position, this.transform.rotation);
//四元数相乘 = 新四元数 相当于旋转量的叠加
//四元数:转多少度 绕哪个轴
Instantiate(bullet, this.transform.position, this.transform.rotation * Quaternion.AngleAxis(-20,Vector3.up));
Instantiate(bullet, this.transform.position, this.transform.rotation * Quaternion.AngleAxis(20, Vector3.up));
break;
case E_TypeFire.Four:
float angle = 360 / num;
for(int i = 0; i < num; i++)
{
//0 90 180 270
Instantiate(bullet, this.transform.position, this.transform.rotation * Quaternion.AngleAxis(i * angle,Vector3.up));
}
break;
}
}
}
四元数计算练习2
public class CameraMove : MonoBehaviour
{
//目标对象
public Transform cube;
//头顶偏移
public int headOffset;
//倾斜角度
public int rotaAngle;
//观测距离
public float distance;
Vector3 nowPos;
void Start()
{
}
// Update is called once per frame
void Update()
{
distance += Input.GetAxis("Mouse ScrollWheel");
distance = Mathf.Clamp(distance, 2, 10);
//头顶偏移
this.nowPos = cube.position + cube.up * headOffset;
//后方偏移
this.nowPos = cube.position +Quaternion.AngleAxis(rotaAngle,cube.right) * -cube.forward * distance;
this.transform.position = nowPos;
Quaternion q = Quaternion.LookRotation(-(Quaternion.AngleAxis(rotaAngle, cube.right) * -cube.forward));
this.transform.rotation = Quaternion.Slerp(this.transform.rotation,q,Time.deltaTime * 5f);
}
}
范围检测练习
//范围检测分为三种 盒 胶囊 圆
//盒参数 中心点 大小 旋转角度 层级 是否忽略触发器
//胶囊参数 起点 终点 大小 层级 是否忽略触发器
//圆参数 中心点 半径 层级 是否忽略触发器
void Update()
{
this.transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime * Input.GetAxis("Vertical"));
this.transform.Rotate(Vector3.up, rotaSpeed * Time.deltaTime * Input.GetAxis("Horizontal"));
if(Input.GetKeyDown(KeyCode.J))
{
Collider[] colliders = Physics.OverlapBox(this.transform.position + this.transform.forward,
Vector3.one,
this.transform.rotation,
1 << LayerMask.NameToLayer("Monster"),
QueryTriggerInteraction.UseGlobal);
for(int i = 0; i < colliders.Length; i++)
{
print(colliders[i].name);
}
}
if (Input.GetKeyDown(KeyCode.K))
{
Collider[] colliders2 = Physics.OverlapCapsule(this.transform.position, this.transform.position + this.transform.forward * 5,
0.5f,
1 << LayerMask.NameToLayer("Monster"));
for (int i = 0; i < colliders2.Length; i++)
{
print(colliders2[i].name);
}
}
if (Input.GetKeyDown(KeyCode.L))
{
Collider[] colliders3 = Physics.OverlapSphere(this.transform.position,10,
1 << LayerMask.NameToLayer("Monster"));
for (int i = 0; i < colliders3.Length; i++)
{
print(colliders3[i].name);
}
}
射线检测练习
//射线检测
//实例化一条射线 第一个参数是起点 第二个参数是方向向量
//射线检测RayCast的参数 射线 最大距离 层级 是否忽略触发器(只能判断是否碰撞 获取不到碰撞的对象)
//所以使用另一个重载 就是射线改为 起点 和 方向
//获取相交物体单个的信息
//RaycastHit的参数 射线 out(返回数据)距离 层级 是否忽略触发器
//获取相交物体多个的信息
//RaycastHitAll的参数 射线 距离 层级 是否忽略触发器
//使用的时候注意看重载 容易记混乱 写错
void Update()
{
#region
//子弹射击练习
this.transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime * Input.GetAxis("Vertical"));
this.transform.Rotate(Vector3.up, rotaSpeed * Time.deltaTime * Input.GetAxis("Horizontal"));
Ray y = Camera.main.ScreenPointToRay(Input.mousePosition);
Debug.DrawLine(y.origin,y.direction);
if (Input.GetMouseButtonDown(0))
{
if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out hit,1000,1 << LayerMask.NameToLayer("Monster")))
{
//创建打击特效
GameObject eff = Instantiate(Resources.Load<GameObject>("eff"));
//设置特效点位置
//位置有重合 让特效在外面一点
eff.transform.position = hit.point + hit.normal * 0.5f;
//设置角度朝向自己
//四元数API中写入法向量 得到一个朝向自己的四元数 赋值给旋转
eff.transform.rotation = Quaternion.LookRotation(hit.normal);
}
}
#endregion
//game窗口随意拖动立方体练习
if(Input.GetMouseButtonDown(0))
{
if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out hit, 1000,1 << LayerMask.NameToLayer("Cube")))
{
//设置cube的transform 就是 碰撞物
cube = hit.transform;
}
}
//长按移动
if(Input.GetMouseButton(0) && cube != null)
{
//射线检测 地板
//根据地板点击碰撞点的位置 设置cube的位置
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit, 1000, 1 << LayerMask.NameToLayer("Floor")))
{
//设置立方体等于地板上的点
//偏移一定高度 让cube在地板上 而不是和地板重合或者在下面
cube.position = hit.point + Vector3.up * 0.55f;
}
}
if(Input.GetMouseButtonDown(1))
{
cube = null;
}
}