Unity3D学习笔记(七):叉乘和四元素

向量的叉乘:
数学运算: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;
    }
}

猜你喜欢

转载自www.cnblogs.com/ciaowoo/p/10362875.html