咱今天開始從腳本來解析具體的功能實(shí)現(xiàn)以及一些技巧
如圖:
?這是當(dāng)前所有腳本所在文件夾,其類別也以及分好了,這期我們就先從最基礎(chǔ)的角色控制相關(guān)腳本開始吧。
打開Scripts/Gameplay/Managers中的Player Input Handler腳本
打開了以后看到最后其在267行左右,對(duì)于剛學(xué)習(xí)的各位來說這樣密密麻麻的代碼看著就是腦瓜子嗡嗡的,特別是沒有計(jì)算機(jī)基礎(chǔ)的同學(xué)更是雪上加霜,所以我們?cè)陂喿x代碼的時(shí)候我們先看把整個(gè)腳本根據(jù)不同函數(shù)體,聲明,以及其他模塊。先區(qū)分到底有多少個(gè)這種部分,然后我們?cè)購牡谝粋€(gè)開始慢慢解析,如圖:
乍一看光是函數(shù)體還是很多,然后就腦補(bǔ)出了這些函數(shù)如何如何的負(fù)責(zé)相互調(diào)用各種嵌套啥的,直接勸退(至少我是這樣的),但是我們注意觀察函數(shù)命名就可以看出其實(shí)是幾個(gè)功能的不同流程,整合之后的函數(shù)就是這個(gè)腳本的所有功能也就是 以下幾個(gè):
1.CanProcessInput()?? : 判斷當(dāng)前能否讀取用戶輸入
2.GetMoveInput()? :移動(dòng)
3.GetLookInputsHorizontal(),GetLookInputsVertical() ?? :獲取視角軸
4.GetJumpInputDown(),GetJumpInoutHeld()? :跳躍
5.GetFireInputDown(),GetFireInputRealesed(),GetFireInputHeld()? :開火
6.GetAimInputHeld()? :瞄準(zhǔn)
7.GetSprintInputHeld()? :沖刺
8.GetCrouchInputDown() ,GetCrouchInputRealesed() :下蹲
9.GetReloadButtonDown()? :裝彈
10.GetSwichWeaponInput()? :切換武器
11.GetSelectWeaponInput() :選擇武器
12.GetMouseOrStickLookAxis()? :獲取鼠標(biāo)或者控制桿的軸
以上這幾個(gè)功能就是一個(gè)游戲?qū)ο髶碛形淦鞯那闆r下的基本行為組成,如果去掉武器組,整個(gè)模塊可以砍一半左右(差不多5個(gè))。
但是注意?。?!在此腳本中所有方法都只是注冊(cè)了,但是都沒有在本腳本中調(diào)用(延遲幀中檢查是否開火了也只是為了其他函數(shù)服務(wù)的一個(gè)條件)
現(xiàn)在我們就能感覺到整個(gè)腳本的結(jié)構(gòu)以及功能組成,就不會(huì)覺得無從下手了,當(dāng)然以后大家再開發(fā)設(shè)計(jì)的時(shí)候也盡量模塊分明減少整個(gè)程序的耦合性,調(diào)用也更方便。
現(xiàn)在我們?cè)倩氐介_頭,我這里為了避免理解歧義我直接翻譯原注釋。
上圖中的Tooltip其實(shí)屬于編輯器擴(kuò)展的相關(guān)應(yīng)用,作用也不是高大上,就是將你當(dāng)前的公開的變量在檢查面板上有一個(gè)注釋
鼠標(biāo)放上去就會(huì)有自定義得內(nèi)容,需要注意你用這個(gè)工具那么對(duì)應(yīng)的變量一定是可以在檢查面板出現(xiàn)的,不然沒有任何意義(因?yàn)槟氵B變量都看不見怎么看他的注釋)。
void start():
在start函數(shù)中就做了三件事:① :獲取m_PlayerCharacterController 引用,做空引用錯(cuò)誤處理。
????????????????????????????????????????????? ② :獲取m_GameFlowManager引用,做空引用錯(cuò)誤處理。
????????????????????????????????????????????? ③ :開始游戲時(shí)將光標(biāo)隱藏并且鎖定? Cursor
其實(shí)隨著練習(xí)多了以后各位也會(huì)理解讓一些在程序全局不會(huì)輕易更改的對(duì)象引用從一開始就寫入,這樣就不用頻繁查找一個(gè)基本不變的值,浪費(fèi)時(shí)間,這也算是設(shè)計(jì)模式中的組合模式,即為了在項(xiàng)目中提高代碼復(fù)用性,降低對(duì)象成本而產(chǎn)生的一種模式,例如減少或者完全避免GetComponent<>在Update系列函數(shù)中調(diào)用,在程序一開始獲取其引用。
void LateUpdate():
?游戲運(yùn)行之后每次延遲幀中調(diào)用GetFireInputHeld()函數(shù)并將值賦給這個(gè)全局變量再由他為調(diào)動(dòng)其他函數(shù)的運(yùn)行提供條件。
void CanProcessInput():
?這個(gè)函數(shù)算是整個(gè)行為腳本的基礎(chǔ)條件之一,判斷光標(biāo)是否鎖定狀態(tài)(你是否切換到其他的應(yīng)用去了,或者最小化了)并且游戲還在運(yùn)行沒有達(dá)到任何結(jié)束條件,此時(shí)才會(huì)返回一個(gè)true,即接收用戶的輸入。
Vector3 GetMoveInput():
?GameConstants 腳本是一個(gè)專門管理輸入軸的信息的,如下圖:
這些命名不是憑空自定義的,而是在Unity->Edit->Project Settings->Input Manager 中,如圖:
仔細(xì)看是可以找到所以關(guān)聯(lián)的軸的。
回到函數(shù),當(dāng)可以接收用戶輸入時(shí),創(chuàng)建一個(gè)Vector3變量用于存儲(chǔ)用戶輸入的垂直軸與水平軸的值構(gòu)成的位置信息,然后對(duì)其加以限制,并返回。
float GetLookInput()系列:
?兩個(gè)函數(shù)都是一樣的,只不過調(diào)用的軸名字不同,此處調(diào)用了方法GetMouseOrStickLookAxis()方法,所以我們直接貼出此方法:
?
?
?看起來有點(diǎn)復(fù)雜,代碼量有點(diǎn)多,但其實(shí)也是做了一些完備處理的,其功能為:
①當(dāng)接受用戶輸入時(shí),創(chuàng)建一個(gè)bool 值 isGamePad 來判斷是否有對(duì)應(yīng)的軸stickInputName的輸入,有就是true,沒有就是false。
②創(chuàng)建一個(gè)float值 i 用于記錄一個(gè)輸入的軸值,二元運(yùn)算,根據(jù)當(dāng)前isGamepad的值來決定取的軸值,true取stickInputName,false取mouseInputName。
③判斷是否需要翻轉(zhuǎn)垂直軸,并且將 i 的值與LookSensitivity變量(視角靈敏度)結(jié)合
④當(dāng)讀取到來自stickInput的值時(shí)才做一個(gè)時(shí)間增量的相乘,否則乘以一個(gè)浮點(diǎn)數(shù)
⑤ #if UNITY_WEBGL ~ #endif?? :這是Unity的編譯預(yù)處理指令,在此處的作用其實(shí)就是當(dāng)處在WebGL平臺(tái)時(shí),程序會(huì)保留if其中的語句并執(zhí)行,這里執(zhí)行的就是對(duì)WebGL上鼠標(biāo)速度的調(diào)優(yōu),而如果條件不成立,編譯后將不會(huì)保留其中代碼。
?總結(jié)來說就是獲取軸值并加以修改以后返回一個(gè)float浮點(diǎn)值,然后GetLookInput系列根據(jù)不同軸獲取到不同值,即玩家的移動(dòng)Vector3中x,y,z的值。
然后下一個(gè),GetJumpInput系列:
?大家可以看到,兩個(gè)函數(shù)基本沒有區(qū)別只是調(diào)用了檢測不同狀態(tài)的函數(shù),流程就是檢測是否按下/按住了指定的跳躍鍵,然后返回一個(gè)bool值,其實(shí)寫過一點(diǎn)練習(xí)的應(yīng)該能看出來就是為了后面的地面檢測,以及虛空踏步,多段跳做的條件。
下一個(gè)是GetFireInput系列:
?不能說一模一樣,只能說兩模一樣,只不過判斷的條件bool值置換了,那我們來看看GetFireInputHeld()函數(shù):
?其實(shí)整體與GetMouseOrStickLookAxis()差異不大,獲取對(duì)應(yīng)軸,當(dāng)輸入為操縱桿時(shí)限制輸入的最小響應(yīng)值,可以理解為射速吧(也許),否則輸出其他對(duì)應(yīng)的鍵的軸值,
回到上面的兩個(gè)函數(shù),當(dāng)開火按下時(shí)(GetFireInputDown())必須確定此時(shí)以及收到了輸入的對(duì)應(yīng)軸值信號(hào)并且在上一幀的LateUpdate中檢測的輸入為空,此時(shí)返回true。當(dāng)放開開火鍵時(shí)(GetFireInputReleased())當(dāng)前沒有收到用戶對(duì)應(yīng)輸入且上一幀的LateUpdate中檢測到了輸入,此時(shí)返回true。
然后是GetAimInputHeld()函數(shù)
同樣接收輸入信號(hào),判斷是否接受到了瞄準(zhǔn)操作的軸值并返回對(duì)應(yīng)bool值(功能沒什么要點(diǎn),我就跳過了)
GetSprintInputHeld()函數(shù):
同上,只不過功能為沖刺
GetCrouchInput系列:
同上,功能為下蹲
GetReloadInputDown()函數(shù),也是同上,功能為裝彈
?
GetSwitchWeaponInput():
這里的切換武器功能其實(shí)并不是直接實(shí)現(xiàn),通過他的返回值可以看見其實(shí)這個(gè)函數(shù)返回的是一個(gè)狀態(tài),通過這個(gè)狀態(tài)來改變武器隊(duì)列的index實(shí)現(xiàn)切換,這里的功能是讀取切換武器的軸通過軸的值來做調(diào)動(dòng),可以想一下鼠標(biāo)滾輪。
?GetSelectWeaponInput()函數(shù):
?這個(gè)呢就是一個(gè)狀態(tài)機(jī)了,根據(jù)在指定了鍵的基礎(chǔ)上根據(jù)用戶的輸入返回一個(gè)對(duì)應(yīng)的值,這里的值對(duì)應(yīng)武器的index,然后就可以切換到對(duì)應(yīng)的武器了。文章來源:http://www.zghlxwxcb.cn/news/detail-450747.html
總結(jié)一下:這次的腳本其實(shí)就處理了基本的并且用于玩家的用戶輸入,這也和腳本名很貼合,之所以這么多函數(shù),其實(shí)都是為了復(fù)用性以及減少耦合性,我們?cè)诰幊讨须m然第一時(shí)間想不出來但是我們?cè)诙啻涡薷臅r(shí)應(yīng)該注意到這些方面,這也是一種加快運(yùn)行的方式吧,這篇文章水了3600字左右,本來想著隨便寫一些的,但是為了我自己養(yǎng)成這種習(xí)慣的話我也是堅(jiān)持下來多水了幾個(gè)字(doge),希望各位也能從中找到一些什么,這個(gè)教程呢腳本還是有點(diǎn)多的,按照我的速度可能很水很拖拉,但是能寫就盡量寫吧,至此第一個(gè)腳本到此結(jié)束,感謝我自己。(才第一個(gè)腳本。。。。。瘋了都?。。。?span toymoban-style="hidden">文章來源地址http://www.zghlxwxcb.cn/news/detail-450747.html
到了這里,關(guān)于Unity官方FPS教程(三)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!