被疫情困在家无聊翻翻以前的文章,发现好黑历史啊,虽然是刚学unity的时候写的,后面学习了DX11并且补了3D数学,发现这些问题都是小case了O(∩_∩)O。


在我最近制作的小游戏中,需要实现防御塔面向小兵的功能。(即物体A需要面向物体B)

Unity 计算一个向量在另一个向量上的投影 unity向量归一化_数学


这很容易让人想到Unity中自带的LookAt()函数,可惜Unity自带的LookAt()函数是3D的,如果把他用在2D游戏上,一样会让物体绕X轴和Y轴旋转,这不是我们想要的效果。

既然不能用LookAt()函数,比较朴素或者说比较常用的算法(至少我是这样想到的)就是,既然我们拥有了物体A和物体B的位置,那我们肯定就能算出它们的X轴差长度和Y轴差长度,之后把他抽象成直角三角形,利用反三角函数得出我们需要绕Z轴旋转的角度(在2D中Z轴我们只能看到一个点)

Unity 计算一个向量在另一个向量上的投影 unity向量归一化_unity_02


当时可能是下意识的觉得这方法有一丁点麻烦,也可能觉得为啥unity没有自带LookAt2D()这样的函数,反正就是去搜了一下看下别人或官方有没有更简洁的实现方法。

然后便看到了Unity官方社区中的这个问题 https://answers.unity.com/questions/585035/lookat-2d-equivalent-.html

讨论的质量还是比较高的,其中也有跟我一样思路的人。

其中让我比较在意也是发这篇文章原因的的代码是目前点赞最多(但不是题主指定最佳答案)的回答

transform.right = target.position - transform.position;

Unity 计算一个向量在另一个向量上的投影 unity向量归一化_数学_03


其中transform.right是物体自身的红色轴向(X轴)在世界坐标中所指向的位置

第一眼看上去其实还是有一点小小的不理解的,当时就在想,我知道让transform.right(看贴图,一些是需要调整transofrm.up,原贴链接也有说,这里统一写transofrm.right)指向目标位置就能实现朝向效果了,可问题是为什么两个位置差就能调整transform.right呢?难道在给transform.right赋值时它里面也进行了反三角函数运算吗?(其实这样理解也行啊是吧=_=)
然后我查了一下,看到了有人这样写

// Direction vector towards other object (relative to this transform):
 var directionTo = (other.transform.position - transform.position).normalized;
 
 // align forward axis to direction:
 transform.forward = directionTo;

看到了这个normalized(归一化),才拍脑门想起来这个数学知识点。原来我陷入了思维泥潭,我在做反三角函数时把两个顶点位置相减,是为了得到他们两个的长度差来进行反三角函数运算。但是这里的两个顶点相减是为了获得一个指向对方的向量,再做归一化运算确定方向,原代码为了简洁省去了normalized导致一时没看出来,赋值给transform.right时系统是会做的。

这里给数学基础比较薄弱的人再简介一下向量和向量归一化吧,顺便也当自己的一个小总结。

Unity 计算一个向量在另一个向量上的投影 unity向量归一化_游戏开发_04


这里假设有3个顶点A(1,1),B(2,2),C(3,3),顶点B减顶点A获得了一个由A指向B的向量Unity 计算一个向量在另一个向量上的投影 unity向量归一化_数学_05,顶点C减顶点A获得了一个由A指向C的向量Unity 计算一个向量在另一个向量上的投影 unity向量归一化_C#_06。这个时候我们可以观察到向量Unity 计算一个向量在另一个向量上的投影 unity向量归一化_数学_05与向量Unity 计算一个向量在另一个向量上的投影 unity向量归一化_C#_06的方向其实是一致的,那我们怎么判断向量的方向是否一致(或者说获得它的方向)呢?答案是使用向量归一化来判断,也就是转为单位向量。

我们都知道向量的模(长度)是Unity 计算一个向量在另一个向量上的投影 unity向量归一化_unity_09 (平面向量z==0),而向量归一化就是把向量转换为单位向量,也就是模为1.即找到满足Unity 计算一个向量在另一个向量上的投影 unity向量归一化_游戏开发_10,并且x:y:z的值始终不变(比例不变)的这个方程的解。

在unity中transform.right、transform.up、transoform.right等都是单位向量(所以在赋值时也会自动归一化)