点成叉乘 Unity

在Unity3D中,Vector3.Dot表示求两个向量的点积;Vector3.Cross表示求两个向量的叉积。

点积计算的结果为数值,而叉积计算的结果为向量。两者要注意区别开来。

简单的说,点乘判断角度,叉乘判断方向。

形象的说当一个敌人在你身后的时候,叉乘可以判断你是往左转还是往右转更好的转向敌人,点乘得到你当前的面朝向的方向和你到敌人的方向的所成的角度大小。

1.点积

a·b=|a|·|b|cos<a,b>

  • |a|和|b|表示向量的模
  • <a,b>表示两个向量的夹角。<a,b>和<b,a> 夹角是不分顺序的。
  • 通过点积可以计算两个向量的夹角的。

如果两个向量a,b均 为单位 向量 ,那么a.b等于向量b在向量a方向上的投影的长度

应用

通过点积的计算我们可以简单粗略的判断当前物体是否朝向另外一个物体: 只需要计算当前物体的transform.forward向量与 (otherObj.transform.position – transform.position)的点积即可。

  • 若结果 == 0,则两向量互垂直 。
  • 若结果 > 0 ,则两向量夹角小于90°,当前物体面对
  • 若结果 < 0 ,则两向量夹角大于 90°,当前物体背对

2.叉积

c =a x b

  • 其中a,b,c均为向量。即两个向量的叉积得到的还是向量!
  • 性质1:c⊥a,c⊥b,即向量c垂直与向量a,b所在的平面。
  • 性质2:模长|c|=|a||b|sin<a,b>
  • 性质3:满足右手法则。从这点我们有axb ≠ bxa,而axb = – bxa。所以我们可以使用叉积的正负值来判断向量a,b的相对位置,即向量b是处于向量a的顺时针方向还是逆时针方向。

求两向量夹角

using UnityEngine;  
using System.Collections;  

public class MainScript : MonoBehaviour  
{  
        //向量a  
        private Vector3 a;  
        //向量b  
        private Vector3 b;  

        void Start ()  
        {  
                //向量的初始化  
                a = new Vector3 (1, 2, 1);  
                b = new Vector3 (5, 6, 0);  
        }  

        void OnGUI ()  
        {  
                //点积的返回值  
                float c = Vector3.Dot (a, b);  
                //向量a,b的夹角,得到的值为弧度,我们将其转换为角度,便于查看!  
                float angle = Mathf.Acos (Vector3.Dot (a.normalized, b.normalized)) * Mathf.Rad2Deg;  
                GUILayout.Label ("向量a,b的点积为:" + c);  
                GUILayout.Label ("向量a,b的夹角为:" + angle);  

                //叉积的返回值  
                Vector3 e = Vector3.Cross (a, b);  
                Vector3 d = Vector3.Cross (b, a);  
                //向量a,b的夹角,得到的值为弧度,我们将其转换为角度,便于查看!  
                angle = Mathf.Asin (Vector3.Distance (Vector3.zero, Vector3.Cross (a.normalized, b.normalized))) * Mathf.Rad2Deg;  
                GUILayout.Label ("向量axb为:" + e);  
                GUILayout.Label ("向量bxa为:" + d);  
                GUILayout.Label ("向量a,b的夹角为:" + angle);  
        }  
}  

上面的示例中,我们定义了两个向量a和b。分别求出了他们的点积和叉积,并通过点积和叉积来反过来计算他们的夹角。
这里要说明的是:
1.a.normalized 和 b.normalized 表示的是两个向量的单位向量, 因为在公式里,有向量和模的除法,得出来的结果就是单位向量(单位向量模为1),所以我们这里和后面都直接用单位向量来计算,省去不少麻烦。

2.Mathf.Rad2Deg表示的是 单位弧度的度数。也就是2π/360

3.通过叉积计算度数是通过公式|c|=|a||b|sin<a,b>来逆向求值。|c| 其实就是叉积的模,换句话说,也代表着Vector3.Distance (Vector3.zero, Vector3.Cross (a.normalized, b.normalized))的值。
结果图如下:
[图片上传失败...(image-d2d56f-1649414557572)]

点乘与叉乘项目中的应用

项目需求:
1 通过点乘计算物体B在物体A的前方还是后方
2 通过叉乘,计算物体A转向物体B时,最小角的旋转方向

实现过程:
首先计算出物体A的前方朝向向量v_Bz=B.transform.forward,然后计算物体B相对于物体A的位置向量 v_AB = A.position - B.position;

通过计算v_Bz与v_AB向量点乘结果的正负,判断物体B在物体A的前后
如果物体B在物体A前方, Vector3.Dot(v_Bz,v_AB)大于0
如果物体B在物体A后方, Vector3.Dot(v_Bz,v_AB)小于0

通过计算v_Bz与v_AB向量叉乘的结果,判断旋转方向
如果逆时针旋转,v_C = Vector3.Cross(v_Bz, v_AB)为沿y轴负方向
如果顺时针旋转,v_C = Vector3.Cross(v_Bz, v_AB)为沿y轴正方向

using UnityEngine;
using System.Collections;

public class Vector3_Dot : MonoBehaviour {

    public Transform A, B;
    Vector3 v_Bz, v_AB, v_A,v_B,v_C;
    string str = "";

    // Use this for initialization
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {

        //点乘
        v_Bz = B.transform.forward;//B.transform.TransformDirection(Vector3.forward);
        v_AB = A.position - B.position;
        float f = Vector3.Dot(v_Bz,v_AB);
        if (f>0)
        {
            str = "A在B自身座标系的前方";
        }
        else if (f<0)
        {
            str = "A在B自身座标系的后方";

        }
        else
        {
            str = "A在B自身座标系的左前方或右方";
        }

        //差乘
        v_A = A.position;
        v_B = B.position;
        v_C = Vector3.Cross(v_Bz, v_AB);
       // A.Rotate(0,0,0);

    }

    void OnGUI()
    {
        GUI.Label(new Rect(10,10,200,60),str);

    }

    void OnDrawGizmos()
    {
        //差乘绘制相关线
        Gizmos.color = Color.blue;
        Gizmos.DrawLine(-v_C,Vector3.zero);

        //点乘绘制相关线
        Gizmos.color = Color.yellow;
        Gizmos.DrawLine(Vector3.zero,A.position);

        Gizmos.color = Color.yellow;
        Gizmos.DrawLine(Vector3.zero,B.position);

        Gizmos.color = Color.red;
        Gizmos.DrawLine(A.position, B.position);

        Gizmos.color = Color.red;
        Gizmos.DrawLine(Vector3.zero,v_AB);

        Gizmos.color = Color.green;
       // Gizmos.DrawLine(A.transform.position, Vector3.left);

    }
}

[图片上传失败...(image-ee4442-1649414557572)]

总结

1.判断目标在自己的前后方位可以使用下面的方法:

Vector3.Dot(transform.forward, target.position-transform.position)

返回值为正时,目标在自己的前方,反之在自己的后方

2.判断目标在机子的左右方位可以使用下面的方法:

Vector3.Cross(transform.forward, target.position-transform.position).y

返回值为正时,目标在自己的右方,反之在自己的左方

【参考原文】Unity3D之Vector3.Dot和Vector3.Cross的使用
【参考原文】Unity3D之点乘和差乘

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容