目录
1、叉乘
两个向量叉乘,得到一个新的向量,新向量跟原始两个向量都垂直,也就是得到由两个向量所确定平面的法向量。
a(x, y , z) b(i , j , k)
a * b = (y * k - z * j , x * k - z * i , x * j - y * i)
public class CrossTest : MonoBehaviour
{
public GameObject cube;
public GameObject sphere;
void Update()
{
Vector3 v = sphere.transform.position - cube.transform.position;
Vector3 cross = Vector3.Cross(cube.transform.forward, v);
Debug.DrawLine(cube.transform.position, cube.transform.forward * 10, Color.blue);
Debug.DrawLine(cube.transform.position, sphere.transform.position , Color.red);
Debug.DrawRay(cube.transform.position, cross, Color.green);
if (cross.y > 0)
{
Debug.Log("在右边");
}
else
{
Debug.Log("在左边");
}
}
}
2、四元素
万向节死锁 <x,y,z>
实数:分为有理数和无理数
虚数:i ^ 2 = -1
复数:实数 + 虚数
超复数:(x,y,z,w)
X = n * x * sin(/2)
Y = n * y * sin(/2)
Z = n * z * sin(/2)
W = cos(/ 2)
public class QuaternionTest : MonoBehaviour
{
public GameObject cube;
void Start()
{
cube.transform.rotation = new Quaternion(0, 0, Mathf.Sin(30 * Mathf.Deg2Rad),
Mathf.Cos(30 * Mathf.Deg2Rad));//cube绕z轴旋转60度
Quaternion q1 = Quaternion.Euler(0, 30, 0);
cube.transform.rotation = q1;//cube绕y轴旋转30度
Quaternion q2 = Quaternion.Euler(new Vector3(0, 30, 0));
cube.transform.rotation = q2;
Quaternion q3 = Quaternion.AngleAxis(30, Vector3.forward);
cube.transform.rotation = q3;
}
}
3、四元素旋转
1)、cube位置rest,cube 从沿y轴从0度到60度旋转(Lerp(差值))
public class QuaternionRotate : MonoBehaviour
{
public GameObject cube;
public Transform target;
void Update()
{
Quaternion q2 = Quaternion.Euler(0, 60, 0);
cube.transform.rotation = Quaternion.Lerp(cube.transform.rotation, q2, 0.1f);
Debug.Log("旋转角度:" + cube.transform.rotation.eulerAngles.y);//0-60
Debug.Log("cube.transform.rotation.y" + cube.transform.rotation.y);//0-0.5
}
}
2)、用下面这个方法是错误的,q1的y值一直都是从0 - 32.975变化,没更新一次都执行:Quaternion q1 = Quaternion.Euler(0, 30, 0);
public class QuaternionRotate : MonoBehaviour
{
public GameObject cube;
void Update()
{
Quaternion q1 = Quaternion.Euler(0, 30, 0);
Quaternion q2 = Quaternion.Euler(0, 60, 0);
q1 = Quaternion.Lerp(q1, q2, 0.1f);
cube.transform.rotation = q1;//cube.transform.rotation.eulerAngles.y = 32.975
}
}
正确的做法:q1变量放方法外。
public class QuaternionRotate : MonoBehaviour
{
public GameObject cube;
Quaternion q1 = Quaternion.Euler(0, 30, 0);
void Update()
{
Quaternion q2 = Quaternion.Euler(0, 60, 0);
q1 = Quaternion.Lerp(q1, q2, 0.1f);
cube.transform.rotation = q1;//0 - 60
}
}
3)、旋转看向目标物体
1.LookAt
public class QuaternionLookRotate : MonoBehaviour
{
public GameObject cube;
public Transform target;
void Update()
{
//cube主角z轴瞬间看向目标物体
cube.transform.LookAt(target);
}
}
2.public static Quaternion LookRotation(Vector3 forward);
public class QuaternionLookRotate : MonoBehaviour
{
public GameObject cube;
void Update()
{
Vector3 dir = new Vector3(30, 0, 0);//(30,0,0)相当于(1,0,0)
//cube主角的z轴看向目标物体(dir)即x轴正方向
cube.transform.rotation = Quaternion.LookRotation(dir);
}
}
当改变dir的值时,cube的z轴正方向看向的位置也改变
public class QuaternionLookRotate : MonoBehaviour
{
public GameObject cube;
void Update()
{
Vector3 dir = new Vector3(0, 10, 0);
cube.transform.rotation = Quaternion.LookRotation(dir);
}
}
3.public static Quaternion LookRotation(Vector3 forward, [DefaultValue("Vector3.up")] Vector3 upwards);
public class QuaternionLookRotate : MonoBehaviour
{
public GameObject cube;
public Transform target;
private void Start()
{
Debug.Log("Vector3.up:" + Vector3.up);//(0,1,0)
}
void Update()
{
Quaternion q1 = Quaternion.LookRotation(target.position - cube.transform.position);
cube.transform.rotation = Quaternion.Lerp(cube.transform.rotation, q1, 0.1f);//最后cube的z轴指向target
Debug.DrawLine(cube.transform.position, target.position,Color.blue);
}
}
4、四元素和四元素相乘
就是两个相加
public GameObject cube;
public Transform target;
void Start()
{
Quaternion q1 = Quaternion.Euler(0, 30, 0);
Quaternion q2 = Quaternion.Euler(0, 60, 0);
Quaternion q3 = q1 * q2;
cube.transform.rotation = q3;
Debug.Log("cube.transfor.rotation.eulerAngles: " +
cube.transform.rotation.eulerAngles);
}
5、鼠标控制物体旋转
public class MouseRotate : MonoBehaviour
{
public GameObject cube;
private float mousex;
void Update()
{
mousex = Input.GetAxis("Mouse X");
Quaternion q = Quaternion.AngleAxis(mousex, Vector3.up);
cube.transform.rotation *= q;
}
}
6、发射子弹
biubullet类挂载在发射子弹的主角物体上,一定角度生成子弹
public class biubullet : MonoBehaviour
{
public GameObject bullet;
private float timer;
void Start()
{
bullet = Resources.Load<GameObject>("Prefabs/bullet");
}
void Update()
{
timer += Time.deltaTime;
if(timer > 3)
{
Vector3 dir = Quaternion.AngleAxis(-15, Vector3.up) * transform.forward;
GameObject go = Instantiate(bullet);
go.transform.position = transform.position;
go.transform.rotation = Quaternion.LookRotation(dir);
timer = 0;
}
}
}
BulletController类挂载在子弹上,控制子弹的移动
public class BulletController : MonoBehaviour
{
void Update()
{
transform.Translate(Vector3.forward * 0.01f, Space.Self);
}
}
7、环形发射子弹
设置timer的时间,3秒后发射一次环形子弹,发射完一次环形子弹就将timer设置回0
public class biubullet : MonoBehaviour
{
public GameObject bullet;
private float timer;
void Start()
{
bullet = Resources.Load<GameObject>("Prefabs/bullet");
}
void Update()
{
timer += Time.deltaTime;
if(timer > 3)
{
//for(int i = 0; i < 5; i++)
//{
// Vector3 dir = Quaternion.AngleAxis(-30 + i *15, Vector3.up) * transform.forward;
// GameObject go = Instantiate(bullet);
// go.transform.position = transform.position;
// go.transform.rotation = Quaternion.LookRotation(dir);
//}
//timer = 0;
for (int i = 0; i < 24; i++)
{
Vector3 dir = Quaternion.AngleAxis(-30 + i * 15, Vector3.up) * transform.forward;
GameObject go = Instantiate(bullet);
go.transform.position = transform.position;
go.transform.rotation = Quaternion.LookRotation(dir);
}
timer = 0;
}
}
}
public class BulletController : MonoBehaviour
{
void Update()
{
transform.Translate(Vector3.forward * 0.01f, Space.Self);
}
}
8、子弹缓冲池
1)、PoolMain 缓冲池单例;挂载在创建的缓冲池空物体上
public class PoolMain : MonoBehaviour
{
public static PoolMain Instance;
private void Awake()
{
Instance = this;
}
GameObject bulletPool;
public GameObject GetBulletPool()
{
if(bulletPool == null)
{
bulletPool = GameObject.Find("bulletPool");
}
return bulletPool;
}
}
2)、biubullet 主角控制子弹的生成,缓冲池里没有子物体时克隆子弹(因为每3秒生成一圈子弹,而每5秒后将已生成的子弹设为缓冲池的子物体,所以克隆一圈子弹),缓冲池里有子物体时,就取出子物体。
public class biubullet : MonoBehaviour
{
public GameObject bullet;
private float timer;
void Start()
{
bullet = Resources.Load<GameObject>("Prefabs/bullet");
}
void Update()
{
timer += Time.deltaTime;
if(timer > 3)
{
for (int i = 0; i < 24; i++)
{
GameObject go = null;
//找到缓冲池父物体
GameObject pool = PoolMain.Instance.GetBulletPool();
//判断缓冲池子物体数量是否足够
if(pool.transform.childCount >0)
{
//取缓冲池里的第一个子物体
go = pool.transform.GetChild(0).gameObject;
//把子弹物体迅速从缓冲池物体内取出
go.transform.parent = null;
//将游戏物体(子弹)设置为激活状态
go.SetActive(true);
}
else
{
//缓冲池里没有子物体,就需要克隆子弹
go = Instantiate(bullet);
}
Vector3 dir = Quaternion.AngleAxis(-30 + i * 15, Vector3.up) * transform.forward;
go.transform.position = transform.position;
go.transform.rotation = Quaternion.LookRotation(dir);
}
timer = 0;
}
}
}
3)、BulletController 控制子弹的移动,每5秒后将生成的子弹设置缓冲池物体的子物体,并失活
public class BulletController : MonoBehaviour
{
private float timer;
private GameObject pool;//缓冲池(空物体)
private void Start()
{
pool = PoolMain.Instance.GetBulletPool();
}
void Update()
{
timer += Time.deltaTime;
if(timer > 5)
{
//将生成的子弹的父物体设置为缓冲池物体
transform.parent = pool.transform;
timer = 0;
//作为缓冲池物体的子物体后失活
gameObject.SetActive(false);
}
transform.Translate(Vector3.forward * 0.01f, Space.Self);
}
}