咱今天开始从脚本来解析具体的功能实现以及一些技巧
如图:
这是当前所有脚本所在文件夹,其类别也以及分好了,这期我们就先从最基础的角色控制相关脚本开始吧。
打开Scripts/Gameplay/Managers中的Player Input Handler脚本
打开了以后看到最后其在267行左右,对于刚学习的各位来说这样密密麻麻的代码看着就是脑瓜子嗡嗡的,特别是没有计算机基础的同学更是雪上加霜,所以我们在阅读代码的时候我们先看把整个脚本根据不同函数体,声明,以及其他模块。先区分到底有多少个这种部分,然后我们再从第一个开始慢慢解析,如图:
乍一看光是函数体还是很多,然后就脑补出了这些函数如何如何的负责相互调用各种嵌套啥的,直接劝退(至少我是这样的),但是我们注意观察函数命名就可以看出其实是几个功能的不同流程,整合之后的函数就是这个脚本的所有功能也就是 以下几个:
1.CanProcessInput() : 判断当前能否读取用户输入
2.GetMoveInput() :移动
3.GetLookInputsHorizontal(),GetLookInputsVertical() :获取视角轴
4.GetJumpInputDown(),GetJumpInoutHeld() :跳跃
5.GetFireInputDown(),GetFireInputRealesed(),GetFireInputHeld() :开火
6.GetAimInputHeld() :瞄准
7.GetSprintInputHeld() :冲刺
8.GetCrouchInputDown() ,GetCrouchInputRealesed() :下蹲
9.GetReloadButtonDown() :装弹
10.GetSwichWeaponInput() :切换武器
11.GetSelectWeaponInput() :选择武器
12.GetMouseOrStickLookAxis() :获取鼠标或者控制杆的轴
以上这几个功能就是一个游戏对象拥有武器的情况下的基本行为组成,如果去掉武器组,整个模块可以砍一半左右(差不多5个)。
但是注意!!!在此脚本中所有方法都只是注册了,但是都没有在本脚本中调用(延迟帧中检查是否开火了也只是为了其他函数服务的一个条件)
现在我们就能感觉到整个脚本的结构以及功能组成,就不会觉得无从下手了,当然以后大家再开发设计的时候也尽量模块分明减少整个程序的耦合性,调用也更方便。
现在我们再回到开头,我这里为了避免理解歧义我直接翻译原注释。
上图中的Tooltip其实属于编辑器扩展的相关应用,作用也不是高大上,就是将你当前的公开的变量在检查面板上有一个注释
鼠标放上去就会有自定义得内容,需要注意你用这个工具那么对应的变量一定是可以在检查面板出现的,不然没有任何意义(因为你连变量都看不见怎么看他的注释)。
void start():
在start函数中就做了三件事:① :获取m_PlayerCharacterController 引用,做空引用错误处理。
② :获取m_GameFlowManager引用,做空引用错误处理。
③ :开始游戏时将光标隐藏并且锁定 Cursor
其实随着练习多了以后各位也会理解让一些在程序全局不会轻易更改的对象引用从一开始就写入,这样就不用频繁查找一个基本不变的值,浪费时间,这也算是设计模式中的组合模式,即为了在项目中提高代码复用性,降低对象成本而产生的一种模式,例如减少或者完全避免GetComponent<>在Update系列函数中调用,在程序一开始获取其引用。
void LateUpdate():
游戏运行之后每次延迟帧中调用GetFireInputHeld()函数并将值赋给这个全局变量再由他为调动其他函数的运行提供条件。
void CanProcessInput():
这个函数算是整个行为脚本的基础条件之一,判断光标是否锁定状态(你是否切换到其他的应用去了,或者最小化了)并且游戏还在运行没有达到任何结束条件,此时才会返回一个true,即接收用户的输入。
Vector3 GetMoveInput():
GameConstants 脚本是一个专门管理输入轴的信息的,如下图:
这些命名不是凭空自定义的,而是在Unity->Edit->Project Settings->Input Manager 中,如图:
仔细看是可以找到所以关联的轴的。
回到函数,当可以接收用户输入时,创建一个Vector3变量用于存储用户输入的垂直轴与水平轴的值构成的位置信息,然后对其加以限制,并返回。
float GetLookInput()系列:
两个函数都是一样的,只不过调用的轴名字不同,此处调用了方法GetMouseOrStickLookAxis()方法,所以我们直接贴出此方法:
看起来有点复杂,代码量有点多,但其实也是做了一些完备处理的,其功能为:
①当接受用户输入时,创建一个bool 值 isGamePad 来判断是否有对应的轴stickInputName的输入,有就是true,没有就是false。
②创建一个float值 i 用于记录一个输入的轴值,二元运算,根据当前isGamepad的值来决定取的轴值,true取stickInputName,false取mouseInputName。
③判断是否需要翻转垂直轴,并且将 i 的值与LookSensitivity变量(视角灵敏度)结合
④当读取到来自stickInput的值时才做一个时间增量的相乘,否则乘以一个浮点数
⑤ #if UNITY_WEBGL ~ #endif :这是Unity的编译预处理指令,在此处的作用其实就是当处在WebGL平台时,程序会保留if其中的语句并执行,这里执行的就是对WebGL上鼠标速度的调优,而如果条件不成立,编译后将不会保留其中代码。
总结来说就是获取轴值并加以修改以后返回一个float浮点值,然后GetLookInput系列根据不同轴获取到不同值,即玩家的移动Vector3中x,y,z的值。
然后下一个,GetJumpInput系列:
大家可以看到,两个函数基本没有区别只是调用了检测不同状态的函数,流程就是检测是否按下/按住了指定的跳跃键,然后返回一个bool值,其实写过一点练习的应该能看出来就是为了后面的地面检测,以及虚空踏步,多段跳做的条件。
下一个是GetFireInput系列:
不能说一模一样,只能说两模一样,只不过判断的条件bool值置换了,那我们来看看GetFireInputHeld()函数:
其实整体与GetMouseOrStickLookAxis()差异不大,获取对应轴,当输入为操纵杆时限制输入的最小响应值,可以理解为射速吧(也许),否则输出其他对应的键的轴值,
回到上面的两个函数,当开火按下时(GetFireInputDown())必须确定此时以及收到了输入的对应轴值信号并且在上一帧的LateUpdate中检测的输入为空,此时返回true。当放开开火键时(GetFireInputReleased())当前没有收到用户对应输入且上一帧的LateUpdate中检测到了输入,此时返回true。
然后是GetAimInputHeld()函数
同样接收输入信号,判断是否接受到了瞄准操作的轴值并返回对应bool值(功能没什么要点,我就跳过了)
GetSprintInputHeld()函数:
同上,只不过功能为冲刺
GetCrouchInput系列:
同上,功能为下蹲
GetReloadInputDown()函数,也是同上,功能为装弹
GetSwitchWeaponInput():
这里的切换武器功能其实并不是直接实现,通过他的返回值可以看见其实这个函数返回的是一个状态,通过这个状态来改变武器队列的index实现切换,这里的功能是读取切换武器的轴通过轴的值来做调动,可以想一下鼠标滚轮。
GetSelectWeaponInput()函数:
这个呢就是一个状态机了,根据在指定了键的基础上根据用户的输入返回一个对应的值,这里的值对应武器的index,然后就可以切换到对应的武器了。文章来源:https://www.toymoban.com/news/detail-450747.html
总结一下:这次的脚本其实就处理了基本的并且用于玩家的用户输入,这也和脚本名很贴合,之所以这么多函数,其实都是为了复用性以及减少耦合性,我们在编程中虽然第一时间想不出来但是我们在多次修改时应该注意到这些方面,这也是一种加快运行的方式吧,这篇文章水了3600字左右,本来想着随便写一些的,但是为了我自己养成这种习惯的话我也是坚持下来多水了几个字(doge),希望各位也能从中找到一些什么,这个教程呢脚本还是有点多的,按照我的速度可能很水很拖拉,但是能写就尽量写吧,至此第一个脚本到此结束,感谢我自己。(才第一个脚本。。。。。疯了都!!!)文章来源地址https://www.toymoban.com/news/detail-450747.html
到了这里,关于Unity官方FPS教程(三)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!