向量的叉乘:
数学运算:a(ax,ay,az) x b(bx,by,bz) = c(aybz-azby,azbx-axby,axby-aybx)
几何意义:得到一个新的向量,同时垂直于a向量和b向量,垂直于ab向量所组成的平面,c向量是ab平面的法向量
左手螺旋定则:四指指向a,握向b,大拇指指向c
作用
1、求顺指针,逆时针关系(y>0,y<0)
2、求平面的法向量
四元数(威廉·哈密顿):
万向节死锁(Gimbal Lock):
四元数和欧拉角的优缺点:
欧拉角缺点:万向节死锁 http://v.youku.com/v_show/id_XNzkyOTIyMTI=.html
四元数:xyzw四个分量,w为实部
超复数:是由一个实部 + 三个虚部组成的,如4 + 2i + 3j + 4k
复数:实部 + 虚部,如3 + 2i,5 - 3i。复数的实部为零,即为虚数;虚部为零,即为实数。
----虚数:如果一个数的平方等于负一,那么这个数就是虚数单位,如x^2 = -1,3i,10k,9j
----实数:有理数和无理数的集合
--------有理数:有限的或者无限循环的,如1/3
--------无理数:无限不循环的小数,如PI,e,根号2
四元数中存储的是轴角对儿<n(x,y,z), theta>
x = n.x * sin(theta/2)
y = n.y * sin(theta/2)
z = n.z * sin(theta/2)
w = cos(theta/2)
比如:绕着y轴旋转90度:Quaternion(0,0.707,0,0.707)
1、我们用乘法来表示四元数的旋转量的叠加
欧拉角和四元数互转
public static Quaternion Euler(Vector3 euler); public static Quaternion Euler(float x, float y, float z); public static Quaternion LookRotation(Vector3 forward); public static Quaternion LookRotation(Vector3 forward, [DefaultValue("Vector3.up")] Vector3 upwards);
插值:from + (to - from) * t
线性插值:
public static Vector3 Lerp(Vector3 a, Vector3 b, float t);
a:from是起始的位置
b:to是目标位置
t:在from到to之间插值
using System.Collections; using System.Collections.Generic; using UnityEngine; public class LerpTest : MonoBehaviour { public Transform sphere; // Use this for initialization void Start() { } // Update is called once per frame void Update() { //API:Vector3.Lerp,线性插值,起始位置from,目标位置to,每次插剩余距离(from-to)的百分之多少t transform.position = Vector3.Lerp(transform.position, sphere.position, 0.05f); //Lerp的匀速移动 transform.position = Vector3.Lerp(transform.position, sphere.position, 1/Vector3.Distance(transform.position,sphere.position) * 0.05F); //Lerp的匀速旋转 //API:Mathf.Lerp(); } }
判断方位
using System.Collections; using System.Collections.Generic; using UnityEngine; public class EnemyLookPlayer : MonoBehaviour { public Transform player; public float result1; public float result2; // Use this for initialization void Start () { Vector3 forwardVector = transform.forward; Vector3 enemy2Player = player.position - transform.position; //result1 = enemy2Player.x * forwardVector.x + enemy2Player.y * forwardVector.y + enemy2Player.z + forwardVector.z; result1 = Vector3.Dot(forwardVector, enemy2Player); Vector3 result = Vector3.Cross(forwardVector, enemy2Player); result2 = result.y; } // Update is called once per frame void Update () { } public void OnGUI() { if (result1 > 0) { if (result2 > 0) { GUILayout.Label("玩家在我的方位:右前方"); } else { GUILayout.Label("玩家在我的方位:左前方"); } } else { if (result2 > 0) { GUILayout.Label("玩家在我的方位:右后方"); } else { GUILayout.Label("玩家在我的方位:左后方"); } } } }
路点移动
using System.Collections; using System.Collections.Generic; using UnityEngine; public class FindPath : MonoBehaviour { public Transform[] paths; public Vector3 dir; public float moveSpeed; public float rotSpeed; int index = 0; // Use this for initialization void Start () { } // Update is called once per frame void Update () { if (Vector3.Distance(paths[index].position, transform.position) <= 0.5f) { index++; index %= paths.Length; } dir = paths[index].position - transform.position; transform.Translate(dir *Time.deltaTime* moveSpeed,Space.World); Quaternion targetRotation = Quaternion.LookRotation(dir); transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation,1/ Quaternion.Angle(transform.rotation, targetRotation)* rotSpeed); } }
用单例类来管理路点
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PathManager : MonoBehaviour { //用单例类来管理路点 public static PathManager instanse = null; public static PathManager Instanse { get { return instanse; } } int index = 0; void Awake() { instanse = this; } // Use this for initialization void Start () { //transform.GetChild(1); } // Update is called once per frame void Update () { } public Vector3 GetCurrentPos() { return transform.GetChild(index).position; } public bool IsReached(Vector3 targetPos) { Vector3 currPos = GetCurrentPos(); //忽略路点的高度 currPos.y = targetPos.y; //根据步径调整0.5f的值 return Vector3.Distance(currPos, targetPos) < 0.5f; } public void MoveNext() { index++; //index = index % transform.childCount; index %= transform.childCount; } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class QuaternionTest : MonoBehaviour { public Transform girl; // Use this for initialization void Start() { //把旋转量赋值给transform.rotation transform.rotation = new Quaternion(0, Mathf.Sin(45 * Mathf.Deg2Rad), 0, Mathf.Cos(45 * Mathf.Deg2Rad)); //用乘法表示旋转量叠加 transform.rotation *= new Quaternion(0, Mathf.Sin(45 * Mathf.Deg2Rad), 0, Mathf.Cos(45 * Mathf.Deg2Rad)); //API:Quaternion.AngleAxis,输入轴角对儿,返回四元数,如绕着y轴旋转90度 transform.rotation = Quaternion.AngleAxis(90, Vector3.up); //用乘法表示旋转量叠加,先绕着y轴旋转45度,再绕着y轴旋转90度,结果是-225(135) transform.rotation = Quaternion.AngleAxis(45, Vector3.up) * Quaternion.AngleAxis(90, Vector3.up); //四元数不满足乘法交换律 //先绕着y轴旋转45度,再绕着x轴旋转45度,结果是(45,45,0) transform.rotation = Quaternion.AngleAxis(45, Vector3.up) * Quaternion.AngleAxis(45, Vector3.right); //先绕着x轴旋转45度,再绕着y轴旋转45度 transform.rotation = Quaternion.AngleAxis(45, Vector3.right) * Quaternion.AngleAxis(45, Vector3.up); } // Update is called once per frame void Update() { //API:Quaternion LookRotation(Vector3 forward); Vector3 dir = girl.position - transform.position; //transform.rotation = Quaternion.LookRotation(dir); //目标位置 Quaternion targetRotation = Quaternion.LookRotation(dir); //Slerp球形插值,每次0.01f慢慢插 //transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 0.01f); // transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 1 / Quaternion.Angle(transform.rotation, targetRotation)); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class PlayerControl : MonoBehaviour { public float moveSpeed = 1; public float rotSpeed = 1; public float radius = 5; // Use this for initialization void Start() { } // Update is called once per frame void Update() { Vector3 targetPos = PathManager.Instanse.GetCurrentPos(); Vector3 moveDir = targetPos - transform.position; moveDir.y = 0; //目标与主角y值一致 targetPos.y = transform.position.y; //移动 transform.position = Vector3.Lerp(transform.position, targetPos, 1 / Vector3.Distance(transform.position, targetPos) * moveSpeed); //旋转 transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(moveDir), 1 / Quaternion.Angle(transform.rotation, Quaternion.LookRotation(moveDir)) * rotSpeed); //画线 Debug.DrawLine(transform.position, targetPos, Color.green); //判断是否达到 if (PathManager.Instanse.IsReached(transform.position)) { PathManager.Instanse.MoveNext(); } } private void OnDrawGizmos() { Gizmos.color = new Color(0, 0, 1, 0.3f); Gizmos.DrawSphere(transform.position, radius); } }
补充内容
using System.Collections; using System.Collections.Generic; using UnityEngine; public class w06d3 : MonoBehaviour { public Transform target; public Transform cam; public Vector3 camerPosOffset; public float hOffset; public float moveSpeed = 5; // 1、向量加法的几何意义 // 2、向量减法的几何意义 // 3、向量的点乘的几何意义 // a.b = a.x * b.x + a.y * b.y + a.z * b.z // a.b = |a| * |b| * cos<a, b> // a.b = (|b| * cos<a, b>) * |a| // a.b = (|a| * cos<a, b>) * |b| a向量在b向量上的投影长度 * b向量的模长 // b是单位向量的话, a向量在b向量上的投影长度 // a、b 都是单位向量的话,两个向量的夹角的余弦值 void Start () { if( Vector3.Angle(transform.forward, target.position - transform.position) < 90 ) { } } void Update () { cam.position = transform.position + camerPosOffset; cam.LookAt(transform.position + Vector3.up * hOffset); transform.Translate((target.position - transform.position).normalized * moveSpeed * Time.deltaTime, Space.World); } private void OnTriggerEnter(Collider other) { } private void OnCollisionEnter(Collision collision) { } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Pool<T> where T : UnityEngine.Object { public readonly int Capacity = 50; List<T> items = new List<T>(); public Pool(int capacity = 50) { this.Capacity = capacity; } public bool Push(T item) { if (items.Count >= Capacity - 1) return false; items.Add(item); return true; } public T Pop() { if (items.Count == 0) return default(T); T item = items[items.Count - 1]; items.RemoveAt(items.Count - 1); return item; } }