zoukankan      html  css  js  c++  java
  • 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;
        }
    }
  • 相关阅读:
    常用PHP array数组函数
    每天学习30分钟新知识之html教程1
    laravel学习之路2: jwt集成
    JWT简介json web token bear token
    MDwiki 调研
    laravel学习之路1:认证相关
    OAuth 2.0介绍
    第一行代码 6.4 数据存储全方案-详解持久化数据- 数据库
    github(1)安装及使用图文详解
    Android集成讯飞语音、百度语音、阿里语音识别
  • 原文地址:https://www.cnblogs.com/vuciao/p/10362875.html
Copyright © 2011-2022 走看看