本文解析的是GameCreator中的Shot Camera组件(脚本名为ShotCamera)的 Third Person(脚本类名为ShotTypeThirdPerson);(上图)
对于摄像头的输入模块,可视化编程模块以及属性获取不会涉及;
Third Person中有4个Kernel(以下简称内核), 下面是其在inspector中展示,我们需要记住大致作用和脚本类名
inspector:
作用:
脚本类名:ShotSystemLook
inspector:
作用:
脚本类名:ShotSystemZoom
inspector:
作用:
脚本类名:ShotSystemOrbit
如不清楚某个字段有什么作用,可自行查看官方样例,并且自行设置调试;
类名以I开头的是Interface, 以T开头的是Abstract Class. 以下图中带三角形的箭头是继承, 不带三角形的箭头是组合
class ShotTypeThirdPerson -> abstract class TShotTypeLook -> abstract class TShotType -> interface IShotType
ShotCamera中会有个IShotType的字段, 也就是在inspector里面选的第三人称摄像机的接口,
ShotTypeThirdPerson里面有2个实现IShotSystem接口的字段,然后其父类TShotTypeLook也有个实现IShotSystem接口的ShotSystemLook字段;
接下来将会着重讲解ShotTypeThirdPerson是如何实现第三人称摄像头的
脚本位置如下:
ShotTypeThirdPerson是这个类的派生类, 所以也可以点到基类里面找到
我们可以在Update里面看到这个类是简单处理了摄像头的朝向, 让他看向目标, 不过后续会被其他update覆盖掉;
脚本位置:
ShotTypeThirdPerson是这个类的派生类
这个类里面有3个比较重要的属性:
Level: 表示当前摄像头缩放的比例(0~1)
MinDistance: 表示与目标物体的最小距离
SmoothTime: 表示摄像头缩放到目标缩放的大致时间(用SmoothDamp函数)
在update中, (75行-76行)通过对输入和分辨率的处理, 得到每一帧Level的变化量delta, 然后再用Clamp01()限定在0~1的区别;
最后就是用SmoothDamp()对Level平滑处理:
至此, 我们已经知道了SmoothTime的作用, 但是MinDistance和Level在哪使用我们还不知道, 这2个属性需要在下一个脚本发挥真正作用;
Orbit译为轨道
该脚本位置不再给出, 其就在ShotTypeThirdPerson中可以点入
在ShotTypeThirdPerson的update中, 我们可以看到函数中先执行了ShotSystemZoom对象的update, 在执行ShotSystemOrbit的update之前我们还要执行ShotSystemOrbit的SyncWithZoom函数;
为了搞清楚SyncWithZoom函数干了啥, 我们需要先了解ShotSystemOrbit类的属性.
ShotSystemOrbit在inspector暴露的属性还是很多滴, 其中MaxRadius意为轨道的最大半径, 其会在SyncWithZoom函数中使用
SyncWithZoom函数中会通过Level缩放程度(0~1)乘上最大半径来获得实际轨道的半径, 并且为了与目标有最小距离, 需要加上最小半径;
这样只在ShotSystemZoom中的剩下2个属性就完成了它们的作用.
接下来就是Orbit脚本自己的update函数
首先168行-180行的 if 语句里面会先处理输入, sensitivityX是vertical垂直方向输入, sensitivityY是horizontal水平方向输入;
if (deltaInput == Vector2.zero)
这个判断语句的意思是没有输入, 就会执行ComputeAlign函数()
这个函数中会用到下面3个属性:
m_AlignWithTarget(对应下图中的AlignWithTarget属性):
是否开启对齐物体(意思就是如果很长一段时间(Align Delay属性的值)不移动鼠标, 摄像头就会自动移动到人物的背后看向人物,
与卡拉彼丘游戏中的对齐类似,但不是完全相同,卡拉彼丘无论鼠标移动或不移动,只要超过了一定角度过了段时间就会对齐);
m_AlignDelay:时间限制
m_AlignSmoothTime:平滑对齐时间
下面是ComputeAlign函数, 当到达m_AlignDelay时间后, 就会水平目标角度(m_OrbitAnglesTarget.y)进行平滑处理,
前面是没有输入的情况, 如果有输入就要对目标角度进行增加, 如下函数
ConstrainTargetAngles()函数如下, m_MaxPitch是最大的角度,范围是(1,179),除2后就小于90度.
所以x垂直方向角度是小于90度的,
而y水平方向是在(0,360)范围内
完成以上的角度约束后就可以对rotation进行平滑处理;
接下来包括上面一步的操作都是反逻辑的(我们需要先找到摄像头在目标的什么方向,然后从物体的位置推算出摄像头的位置,而不是先得出位置,再得出方向);
GetTargetPosition函数获取到目标的位置;
lookRotation目标角度对应的四元数,将其与(0,0,1)相乘就得到了我们看向目标物体的方向
(其中原理是四元数乘向量就等于向量旋转,沿着四元数对应的角度);
知道这个向量后,由于知道目标位置,就可以知道当前摄像头的位置,然后求出position.
这样我们就完成了跟随玩家的摄像头;
还有1点需要补充的是整个第三人称摄像头是在LateUpdate中由ShotCamera类(继承了mono)调用的;
下图中m_ShotType就是接口IShotType;其是摄像头的接口;
还剩1个疑问,