Unity精华☀️点乘、叉乘终极教程:用《小小梦魇》讲解这个面试题~

 

 目录

🟥 点乘计算面向还是背向

1️⃣ 面向背向的定义

2️⃣ 《第五人格》应用案例

3️⃣ 推导过程

4️⃣ Unity代码

🟧 叉乘判断物体在自己左边还是右边(顺时针/逆时针)

1️⃣ 《小小梦魇》应用案例

2️⃣ 推导逻辑

3️⃣ Unity代码

🚩 所以在X、Z平面,看Y值

🚩 在X、Y平面,看Z值

🚩 在Y、Z平面,看X值

 🟨 点乘判断角度


面试官:

请讲解一下你对Unity中点乘和叉乘的理解。

我:

额。。点乘和叉乘。。它们可以用来判断方位。。。

哈喽艾薇巴蒂,你的小星河突然出现~

很多小老弟面试时啊,经常被面试官问到这个问题,说实在的,答不上来,

当时空气就瞬间凝固了。。

今天我们就来针对这个问题好好唠一唠,点乘和叉乘使用场景是什么,到底该怎样使用点乘叉乘。

其实我们如果进入游戏制作行业,就会经常用到点乘叉乘了,

  • 比如怪物移动、追踪主角时,判断怪物的是否面向主角、
  • 怪物从自然的向前追,到拐弯搜到主角,这个怪物拐弯身体应旋转多少度、顺时针转还是逆时针转?

🟥 点乘计算面向还是背向

我们先来看第一个问题:

怪物移动、追踪主角时,判断怪物的是否面向主角

1️⃣ 面向背向的定义

我们先来声明一下定义哈

这儿的面向,并不是两个人面对面,而是比如说两个人向前的夹角在0-90度之间。

背向,也不是背靠背,而是方向夹角在90-180度之间。

比如说下图面向:

  

背向:

      

这儿的面向背向属实太忽悠了

2️⃣ 《第五人格》应用案例

比如这个《第五人格》红蝶技能:

第五人格红蝶

离魄移魂:红蝶进入生成状态变为般若相,轻跃向空中俯瞰周身环境,使用此技能可增加刹那生灭的释放距离,但红蝶畏惧他人视线,被求生者注视面部时会变成惊慌相,无法释放刹那生灭。

那么就需要在红蝶进入般若相时,当和玩家在一定距离内,

要检测玩家是否背向自己(背向是方向夹角在90-180之间),

决定自己面部表情、能否释放攻击技能。

3️⃣ 推导过程

根据我们高中学的公式 :a · b = |a|*|b| cosθ,θ∈(0,180)

那么:

  • θ∈(0,90)即面向,点乘结果>0
  • θ∈(90,180)即背向, 点乘结果<0

那么我们只要判断点乘的结果>0,还是<0,就知道面向还是背向了。

知识点:

点乘的结果是float类型

叉乘的结果还是向量

4️⃣ Unity代码

Unity中代码如下:

    public Transform trans00;
    public Transform trans01;

    void Update()
    {
        float result = Vector3.Dot(trans00.forward, trans01.forward);
        print(result);
        if (result == 1)
        {
            print("两物体同向平行");
        }
        else if (result == -1)
        {
            print("两物体反向平行");
        }
        else if (result > 0)
        {
            print("两物体面向");
        }
        else
        {
            print("两物体背向");
        }
    }

🟧 叉乘判断物体在自己左边还是右边(顺时针/逆时针)

橙哥之前看椿主播玩《小小梦魇》时,也太有意思了

但是自己却没时间玩   呜呜

1️⃣ 《小小梦魇》应用案例

在游戏里,玩家藏在了椅子下,怪物追过去,

那怪物是怎么判断出来,玩家在自己左侧还是右侧,从而控制向左转还是向右转,使动画更自然的呢?

有的小老弟就说了:

橙哥,咱们不能使用LookAt吗,或者Dotween的DoLookAt,

实在不行,自动寻路也行呀

首先啊,我们先来说下LookAt,

LookAt是瞬间让自己朝向目标,动作生硬不合适。

如果在Update里时刻朝向,那怪物可能会斜着走路。

DoLookAt确实能解决让怪物看向玩家,也挺好用的,

但是在游戏中,为了让动画自然,我们仍要知道该用向左转,还是向右转的动画,需要判断方位。

自动寻路,只能控制位置移动,不能控制旋转呢。

2️⃣ 推导逻辑

a X b = c , c⊥a,c⊥b。

叉乘得到是:一个与这两个向量都垂直的向量。

这个向量的方向满足右手螺旋法则:

a×b的方向:四指由a开始,指向b,拇指的指向就是a×b的方向,垂直于a和b所在的平面;

b×a的方向:四指由b开始,指向a,拇指的指向就是b×a的方向,垂直于b和a所在的平面;

a×b的方向与b×a的方向是相反的,所以:a×b=-b×a,负号代表的是方向相反。

向量都是有方向的,

比如我们的a、b两个向量(x1,y1,z1)(x2,y2,z2)

都在x、y平面,那这两个向量相乘,结果的x、y值肯定为正,只需判断Z值,根据正负即可知道右手螺旋法则大拇指朝上还是朝下

即可知道b在a的左侧还是右侧。

若都在x、z平面,咋判断y。同理,z、y平面,则判断x

3️⃣ Unity代码

请注意:

Unity当中使用左手,因为Unity使用的是左手坐标系

任意物体的坐标不应是原点,因为0x任何数都为0,判断不了方向。

该代码用来判断trans01在trans00的左边还是右边。

Vector3 result = Vector3.Cross(trans00.position, trans01.position);
print(result);

先说结论:

使用叉乘判断方位,需要看在什么平面、以哪个轴为前方,才能判断。

不同的平面和不同的轴为前方,判断出来的正负不一样。

以下选中的物体为trans01,未选中的为trans00,

举了几个例子作为参考:

🚩 所以在X、Z平面,看Y值

当以Z轴为前方时,

当B在A右侧时,Y值>0

当B在A左侧时,Y值<0

🚩 在X、Y平面,看Z值

当以X轴为前方时,

当B在A右侧时,Y值>0

当B在A左侧时,Y值<0

🚩 在Y、Z平面,看X值

如果以Z轴方向为前方:

当B在A右侧时,X值<0

当B在A左侧时,X值>0

如果以Y轴方向为前方:

当B在A右侧时,X值>0

当B在A左侧时,X值<0

以都在X、Z平面,Z轴为前方来举例:

当B在A右侧时,Y值>0

当B在A左侧时,Y值<0

代码:

    public Transform trans00;
    public Transform trans01;

    void Update()
    {
        Vector3 result = Vector3.Cross(trans00.position, trans01.position);
        print(result);
        if (result.y == 0)
        {
            print("trans01在trans00前方的这条线上");
        }
        else if (result.y > 0)
        {
            print("trans01在右侧");
        }
        else if (result.y < 0)
        {
            print("trans01在左侧");
        }
    }

 🟨 点乘判断角度

最后一个问题,怪物转身,应该转多少度呢?

其实这个点乘和叉乘都能判断角度。

因为:

点乘: a · b = |a|*|b| cosθ

叉乘: |aXb| = |a|*|b|*sinθ

但大家都用点乘来做,那我们也用点乘吧。

看到这是不是这累了,来波福利~

点乘计算的角度跟Vector.Angle结果一致,都是0-180度,用哪个都可以。

Unity公式:

    public Transform trans00;
    public Transform trans01;

    void Update()
    {
        float cosAngle = Vector3.Dot(trans00.forward.normalized, trans01.forward.normalized);
        float angleDot = Mathf.Acos(cosAngle) * Mathf.Rad2Deg;

        float angleVector = Vector3.Angle(trans00.forward, trans01.forward);
        
        print(angleDot);
        print(angleVector);
    }

大家还有什么问题,欢迎在下方留言!


 

在这里插入图片描述


如果你有 技术的问题  项目开发

都可以加下方联系方式

和我聊一聊你的故事🧡

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值