书籍推荐:
3D数学基础:图形与游戏开发——游戏软件开发专家系列(美)邓恩 Unity Shader入门精要 冯乐乐(92年) 数据结构(Python语言描述) 数据结构、算法与应用(C++语言描述) 算法导论 第3版 黑客与画家 程序员生存之道 流体力学:八叉数空间划分
四元数的几个概念:
四元数的模长:Mathf.Sqrt(x^2 + y^2 + z^2 + w^2)
标准四元数:模长为1的四元数叫标准四元数:在Unity中所有用来表示旋转的四元数都是标准四元数
单位四元数:[0,0,0,1],单位四元数表示无旋转,Quaternion.identity
共轭四元数:让原四元数虚数部分取负,让原四元数反向旋转,Unity中没有共轭四元数
四元数 * 共轭四元数 = 单位四元数
四元数的逆:类似求导,
四元素的逆 = 共轭四元数 / 四元数的模长,即q-1 = *q / |q|
在Unity中,因为所有表示旋转的四元数都是标准四元数,模长均为1,所以四元素的逆 = 共轭四元数
四元数让向量旋转:
四元数不仅可以旋转点,还可以旋转向量
using System.Collections; using System.Collections.Generic; using UnityEngine; public class RotateVector : MonoBehaviour { // Use this for initialization void Start () { Vector3 dir = new Vector3(1,0,1); Debug.DrawLine(Vector3.zero,dir,Color.red,1000); //单位四元数表示无旋转 Debug.Log(Quaternion.identity); //四元数的逆 Quaternion q = Quaternion.AngleAxis(90, Vector3.up); Quaternion tempQ = Quaternion.Inverse(q); Debug.Log(q); Debug.Log(tempQ); //旋转四元数 Quaternion rotateQ = Quaternion.AngleAxis(45, Vector3.up); Vector3 newVector = rotateQ * dir; Debug.DrawLine(Vector3.zero, newVector, Color.green, 1000); //自己写一个RotationAround //RotateAround(Vector3 point, Vector3 axis, float angle); } // Update is called once per frame void Update () { } }
四元数和欧拉角的优缺点:
1、欧拉角的优点:
(1)、可以同时绕着三根轴一起旋转
(2)、欧拉角节省内存,节省33.3333%的内存
(3)、直观
2、欧拉角的缺点:
(1)、万向节死锁
(2)、误差大
1、四元数的优点:
(1)、没有万向节死锁
(2)、误差小
(3)、可以绕任意一根轴旋转
2、四元数的缺点:
(1)、只能一根一根轴旋转
(2)、比欧拉角多了33.3333%的内存
(3)、不直观
锁可以固定游戏物体的检视面板,方便把其他游戏物体拖拽进来
![](https://img2018.cnblogs.com/blog/1517599/201902/1517599-20190211185940119-481044117.png)
models和prefabs的区别
models模型拖到场景,再拖回资源,可以变成预制体
四方连续,向四周重复地连续和延伸扩展而成的图案形式。
二方连续,向上下或左右两个方向反复连续而形成的纹样。
世界坐标系转屏幕坐标系
Vector2 screenPos = Camera.main.WorldToScreenPoint(target.position);
屏幕坐标系转世界坐标系
Vector3 worldPos = Camera.main.ScreenToWorldPoint(new Vector3(Screen.width, Screen.height, -Camera.main.transform.position.z));
using System.Collections; using System.Collections.Generic; using UnityEngine; public class RotateAroundScript : MonoBehaviour { public Transform sphere; public float rotateSpeed = 1; // Use this for initialization void Start () { } // Update is called once per frame void Update () { //调用RotateAround RotateAround(sphere.position, Vector3.up, rotateSpeed); } public void myRotateAround(Vector3 point, Vector3 axis, float angle) { Vector3 A = transform.position - point; //Vector3 n = Vector3.Project(); //Vector3.Dot(axis, A) = | n | * axis.magnitude; //| n | = Vector3.Dot(axis, A) / axis.magnitude; //Vector3 n = axis.normalized * | n |; Vector3 n = axis.normalized * Vector3.Dot(axis, A) / axis.magnitude; Vector3 a = A - n; Quaternion q = Quaternion.AngleAxis(angle, axis); Vector3 b = q * a; } }
复习
using System.Collections; using System.Collections.Generic; using UnityEngine; public class w06d4 : MonoBehaviour { public Transform target; public Vector3 cubeSize; //欧拉角是如何表示旋转的 //使用x y z来表示旋转 x表示绕x轴旋转多少度 y表示绕y轴旋转多少度 z表示绕z轴旋转多少度 //四元数是如何表示旋转的 //使用x y z w来表示旋转 通过轴角对来表示旋转 n轴转45度 x = n.x * sin<theta/2> , y = n.y * sin<theta/2>, z = n.z * sin<theta/2>, w = cos<theta/2> //欧拉角和四元数的优缺点 //欧拉角 // 优点: 直观,容易理解 // 缺点: 有万向节锁 // 只能绕固定轴旋转 // 不能实现旋转的平滑差值 //四元数 // 优点: 可以实现任何角度的旋转 // 可以实现旋转叠加 // 没有万向节锁 、 // 可以绕任意轴旋转 // 可以实现旋转的平滑差值 // 缺点: 不直观,不容易理解 //API //使当前游戏物体的旋转变为 绕x轴旋转90 //1)、使用欧拉角的形式赋值 //transform.eulerAngles = new Vector3(90, 0, 0); // 使用四元数的形式赋值 //transform.rotation = Quaternion.AngleAxis(90, Vector3.right); //2)、使当前游戏物体直接看向目标 transform.LookAt(target); transform.rotation = Quaternion.LookRotation(target.position - transform.position); //3)、使当前游戏物体缓缓看向目标 transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(target.position - transform.position), 1/Quaternion.Angle(transform.rotation, Quaternion.LookRotation(target.position - transform.position))); //4)、把一个欧拉角转换为四元数 transform.rotation = Quaternion.Euler(0, 45, 0); //5)、使用鼠标的水平轴值控制当前物体旋转(使用四元数叠加) float mouseX = Input.GetAxis("Mouse X"); //自身的 绕Y轴转 XX 度 transform.rotation *= Quaternion.Euler(0, mouseX, 0); //世界的 绕Y轴转 XX 度 transform.rotation = Quaternion.Euler(0, mouseX, 0) * transform.rotation; void Start () { transform.rotation = Quaternion.AngleAxis(90, Vector3.right); transform.eulerAngles = new Vector3(90, 0, 0); transform.LookAt(target); transform.rotation = Quaternion.LookRotation(target.position - transform.position); transform.rotation = Quaternion.Euler(0, 45, 0); } void Update () { transform.rotation = Quaternion.Slerp( transform.rotation, Quaternion.LookRotation(target.position - transform.position), 1 / Quaternion.Angle(transform.rotation, Quaternion.LookRotation(target.position - transform.position))); float mouseX = Input.GetAxis("Mouse X"); // 自身的 绕Y轴转 XX 度 transform.rotation *= Quaternion.Euler(0, mouseX, 0); // 世界的 绕Y轴转 XX 度 transform.rotation = Quaternion.Euler(0, mouseX, 0) * transform.rotation; } private void OnDrawGizmos() { Gizmos.color = new Color(0, 1, 0, 0.2f); Gizmos.DrawSphere(transform.position, 10); } private void OnDrawGizmosSelected() { Gizmos.color = Color.red; Gizmos.DrawCube(transform.position, cubeSize); } }