




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
摘要隨互聯(lián)網(wǎng)信息時(shí)代改變?nèi)藗兩蠲芮邢嚓P(guān)的方方面面,而游戲和虛擬現(xiàn)實(shí)事業(yè)憑借著和互聯(lián)網(wǎng)的高契合性受到許多人對其的看好和關(guān)注。其中,射擊類游戲可以給玩家們最為酣暢淋漓的快感,此類游戲不僅能消除人們在生活中的壓力,在游戲中更能鍛煉到反應(yīng)速度和心態(tài),同時(shí)還能提高對緊急情況的應(yīng)變能力,有著極廣的受眾群體。Unity3D游戲引擎憑借其較低的入門難度,開發(fā)速度迅速的特點(diǎn)在近幾年來在市場中逐漸為大眾所知所用。本論文探究基于Unity3d的軍事模擬演練游戲開發(fā)與實(shí)現(xiàn),跟隨的游戲的趨勢,是一款兼容了第一人稱和第三人稱的射擊游戲,該游戲可以自由的切換人稱來符合不同玩家的需求,同時(shí)添加了大逃殺元素,以添加大地圖以及搜集物資的模式使得該游戲充滿了各種隨機(jī)性要素,變成了一款玩法更加豐富的射擊游戲,需要玩家時(shí)刻保持警覺,眾多的藏身地和遮擋物使得該游戲更具策略性,與槍法成為游戲的雙核心。而這種結(jié)合隨著2017年3月《絕地求生》的發(fā)布引發(fā)熱潮,眾多游戲廠商為了迎合市場開發(fā)了一系列的大逃殺游戲,至今火熱,可見擁有著客觀的發(fā)展前景。本文主要描述該游戲結(jié)合引擎的開發(fā)原理,游戲的設(shè)計(jì)與代碼實(shí)現(xiàn),同時(shí)對于游戲畫面的處理以及最終游戲功能測試,希望對后續(xù)開發(fā)同類型游戲的開發(fā)者提供思路以及參考。關(guān)鍵詞:Unity3D;動(dòng)作;射擊;大逃殺
AbstractAstheInternetinformationagechangesallaspectsofpeople’slivesthatarecloselyrelated,gamesandvirtualrealityarehighlyvaluedandconcernedbymanypeoplefortheirhighcompatibilitywiththeInternet.Amongthem,shootinggamescangiveplayersthemostheartypleasure.Suchgamescannotonlyeliminatethepressureofpeopleinlife,butalsoexercisethereactionspeedandmentalityinthegame,whilealsoimprovingtheabilitytorespondtoemergencies.,Withaverywideaudience.TheUnity3Dgameengine,withitslowentrydifficultyandrapiddevelopmentspeed,hasgraduallybecomeknowntothepublicinthemarketinrecentyears.ThispaperexploresthedevelopmentandimplementationofamilitarysimulationexercisegamebasedonUnity3d.Thetrendofthegamethatfollowsisashootinggamethatiscompatiblewiththefirst-personandthird-personshootinggames.Thegamecanfreelyswitchthepersontomeettheneedsofdifferentplayers.TheBattleRoyaleelements,themodeofaddinglargemapsandcollectingmaterialsmakethegamefullofvariousrandomelements,andithasbecomeashootinggamewithrichergameplay.Playersneedtobealertatalltimes,andtherearemanyhidingplacesandocclusions.Thingsmakethegamemorestrategic,andthemarksmanshipbecomesthedualcoreofthegame.Withthereleaseof"JediSurvival"inMarch2017,alotofgamemanufacturershavedevelopedaseriesofbattleroyalegamestocatertothemarket.Sofar,ithasshownanobjectivedevelopmentprospect.Thisarticlemainlydescribesthedevelopmentprincipleofthegamecombiningengine,gamedesignandcodeimplementation.Atthesametime,fortheprocessingofthegamescreenandthefinalgamefunctiontest,Ihopetoprovideideasandreferenceforsubsequentdeveloperswhodevelopthesametypeofgame.Keywords:Unity3D;Action;Shooting;BattleRoyale廣東東軟學(xué)院本科畢業(yè)設(shè)計(jì)(論文)目錄TOC\o"1-3"\h\u第一章緒論 緒論選題的目的和意義隨著時(shí)代的變遷,人類的娛樂活動(dòng)逐漸從實(shí)體轉(zhuǎn)移到了虛擬物體上。計(jì)算機(jī)網(wǎng)絡(luò)的普及,使人與人之間的聯(lián)系變得更為接近,即便是千里之外,亦能共享娛樂帶來的樂趣。毫無疑問的說,虛擬娛樂方式的出世,極大的豐富了人們的娛樂方式,給人提供了釋放生活壓力的新方式,隨著人們對游戲的探究以及設(shè)備硬件的提高,人們越來越追求更加真實(shí)的感官,更深的浸入感,而能使玩家更能融入其中的3D游戲已經(jīng)為市場主流。而論最能釋放壓力的游戲方式,則是為緊張刺激的射擊類游戲,由其衍生出來的大逃殺模式更是能讓人體會(huì)到腎上腺素飆升的快感。本次論文選擇的游戲引擎為時(shí)下流行的Unity3d引擎,Unity3D是讓開發(fā)者玩家輕松創(chuàng)建三維模型可視化與渲染,現(xiàn)代化用戶交互界面程序或時(shí)下火熱的高性能3A游戲大作等多樣化互動(dòng)類型的多平臺(tái)兼容的綜合型游戲開發(fā)工具,最為顯著的特點(diǎn)是集成度高,開發(fā)門檻低,很適合第一次接觸游戲制作的開發(fā)者的一款引擎軟件。Unity3D引擎(簡稱U3D)在眾多游戲引擎中,算是比較年輕的一個(gè)引擎,由于近年來需求大量高科技人才,而U3D以他不高的入門門檻以及高便利性迅速的火了起來,以至于各大公司對于能夠熟練使用U3D開發(fā)軟件的人求賢若渴。作為一個(gè)主打游戲的引擎,在其他比如展廳項(xiàng)目、渲染效果圖等領(lǐng)域也開拓了一大塊市場。而憑借U3D相比其他引擎較為短暫的入門周期,客觀理想的市場前景,使得如今各大高校也將U3D引擎的學(xué)習(xí)列入了一門專門課程,從側(cè)面也可以看出社會(huì)上能夠熟練的使用U3D制作游戲的人才可以得到薪資豐厚的工作,結(jié)合以U3D如今的發(fā)展趨勢,毫無疑問學(xué)習(xí)該引擎是一個(gè)不會(huì)令人后悔的選擇。本文正是想要通過自行制作游戲去理解游戲的整個(gè)流程,熟悉游戲制作上的相關(guān)技術(shù)。本次選擇的為時(shí)下大熱的“絕地求生”游戲,由于日常也有玩過這個(gè)游戲,對流程比較熟悉,所以具體闡述游戲的框架以及制作過程。而游戲本身的趣味性是毋庸置疑的,射擊類游戲本身就有著極高的樂趣,每次命中敵人都有著一種獨(dú)特的快感,而且在現(xiàn)實(shí)生活中由于體力和體能的限制,并不是每個(gè)人都可以持槍射擊和奔跑,而在虛擬模擬演練中,可以盡情的奔跑和射擊,進(jìn)可持槍攻敵,退可伏地陰人??梢院痛蠹乙黄馉帄Z空投,游戲的多樣化帶了的娛樂性是十分豐富的。研究現(xiàn)狀自1981年,任天堂的拿手好作品《DonkeyKong》登場拉開帷幕以來,至今游戲行業(yè)的發(fā)展已歷經(jīng)幾輪巨變。遙想當(dāng)年,游戲界尚處于萌芽階段,主人公馬里奧第一次出現(xiàn)在大眾視野中,何人曾猜到這個(gè)普通的水管工能擔(dān)任后來任天堂的首席形象代表,那時(shí)正是街機(jī)游戲百花齊放的12年,游戲行業(yè)的開始了蓬勃發(fā)展,其中日本更是為此行業(yè)的霸主。3D游戲的起源來自于90年代的美國,自3D游戲引擎的問世后瞬間擴(kuò)展全球。從那時(shí)候開始,游戲產(chǎn)業(yè)的豐厚收入甚至超過了傳統(tǒng)工業(yè),巨大的市場使世界各大經(jīng)濟(jì)強(qiáng)國重新開始審視游戲行業(yè),游戲產(chǎn)業(yè)的地位也逐漸水漲船高,。中韓國政府對于游戲的大力支持使得韓國能夠后來居上,如今的游戲發(fā)展規(guī)模已經(jīng)和當(dāng)初的霸主日本平分秋色,而韓國發(fā)展的最為優(yōu)秀的網(wǎng)絡(luò)游戲方面更是奪得了亞洲的王冠,而如今韓國的經(jīng)濟(jì)支柱之一已經(jīng)妥妥的由游戲產(chǎn)業(yè)帶來的效益支撐。結(jié)合我國之前的發(fā)展需求以及傳統(tǒng)觀點(diǎn)的影響,游戲行業(yè)在我國發(fā)展處于起步晚、經(jīng)驗(yàn)不足的情況。并且由于經(jīng)濟(jì)實(shí)力以及開發(fā)周期等原因,除了大型公司,國內(nèi)多數(shù)公司在權(quán)衡利弊之后,還是更加穩(wěn)妥的選擇了國外更為成熟的游戲引擎工具,眾多引擎之中,Unity3D和虛幻在我國最為青睞,兩大巨頭平分秋色。但今年來我國游戲的收入也有著顯著的提升,伽馬數(shù)據(jù)REF_Ref25256\w\h[1]REF_Ref19843\w\h[12]發(fā)布《2019中國游戲產(chǎn)業(yè)年度報(bào)告》顯示,2019年我國游戲市場實(shí)際銷售收入2330.2億元,同比增長8.7%,用戶規(guī)模、自主研發(fā)、海外市場等主要指標(biāo)均明顯好于去年同期。目REF_Ref19758\w\h[13]前中國自主研發(fā)的移動(dòng)游戲在美、日、韓、英、德等國家的流水同比增長率均高于該國移動(dòng)游戲市場的增速,表明國產(chǎn)移動(dòng)游戲在海外市場已經(jīng)建立一定的創(chuàng)新優(yōu)勢。將游戲與文化結(jié)合是打造精品的重要方向。2019年上半年,游戲廠商游族網(wǎng)絡(luò)海外地區(qū)營業(yè)收入達(dá)到10.09億元,占總營業(yè)收入的58.36%。得到海外市場認(rèn)可,很重要一點(diǎn)就是文化融入??梢钥闯鲭S著移動(dòng)硬件設(shè)備的提升,移動(dòng)游戲也開始了驚人的增長,同時(shí)移動(dòng)電競成為了產(chǎn)業(yè)發(fā)展的主要驅(qū)動(dòng)力。很多游戲產(chǎn)品正突破技術(shù)壁壘提高體驗(yàn),VR、AR游戲逐漸普及。REF_Ref19879\w\h[14]隨著5G商用正式啟動(dòng)、基站不斷完善擴(kuò)展,高速便捷的網(wǎng)絡(luò)基礎(chǔ)推動(dòng)了游戲產(chǎn)業(yè)諸多創(chuàng)新。其中,云游戲以云計(jì)算等技術(shù)基礎(chǔ),將游戲在服務(wù)器端運(yùn)行,通過網(wǎng)絡(luò)傳送給用戶,破解游戲?qū)Ω叨穗娔X配置等的依賴,成為當(dāng)前創(chuàng)新的主要方向之一。一旦普遍,移動(dòng)端市場將會(huì)進(jìn)一步擴(kuò)大,而Unity3D的跨平臺(tái)特性將會(huì)具備巨大優(yōu)勢,熟練使用該引擎有著不可忽視的戰(zhàn)略意義。論文組織結(jié)構(gòu)?論文從構(gòu)思設(shè)計(jì),參考著相關(guān)的博客以及技術(shù)書籍,整合了前人的經(jīng)驗(yàn),完成了一個(gè)模擬軍事演練的槍戰(zhàn)游戲制作。下文將通過游戲的制作展示U3D的相關(guān)組件和操作,同時(shí)也分享一下有關(guān)于游戲的制作流程和個(gè)人制作該游戲的心得,其中著重分享游戲的功能設(shè)計(jì)及其代碼的編寫實(shí)現(xiàn)?,F(xiàn)將論文根據(jù)游戲制作過程分解成主要的六大章,各章節(jié)的如下安排:第一部分:緒論,主要闡述了該畢業(yè)設(shè)計(jì)制作的背景、國內(nèi)外對相關(guān)課題的研究現(xiàn)狀以及本設(shè)計(jì)的大概介紹;?
第二部分:對U3D的部分功能進(jìn)行介紹,并且推薦以下本游戲制作過程中使用到的各類開發(fā)工具以及引用的插件。第三部分:講述游戲的場景以及用戶交互界面的設(shè)計(jì)使用到的組件及實(shí)現(xiàn)。 第四部分:詳細(xì)介紹游戲的各個(gè)模塊的制作,清晰明確游戲內(nèi)部關(guān)系,采用由下到上的順序?qū)訉硬鹞霾襟E直觀介紹下整個(gè)游戲流程以及游戲框架的設(shè)計(jì)和搭建,并且展示游戲中各模塊比較核心的腳本源代碼,采用由主及枝詳細(xì)解析各步驟。
第五部分:闡述一些屏幕后處理以及著色器的實(shí)現(xiàn)。第六部分:展示一下游戲運(yùn)行數(shù)據(jù)以及測試結(jié)果。第七部分:制作該游戲的心得,針對游戲中一些不足和缺陷進(jìn)行總結(jié),以及如何改良。?
Unity游戲引擎及插件軟件介紹Unity3D游戲引擎Unity3D引擎介紹Unity3D引擎(以下簡稱U3D)是UnityTechnologies研發(fā)的讓玩家輕松創(chuàng)建豐富的互動(dòng)內(nèi)容軟件的多平臺(tái)的綜合型游戲開發(fā)工具,完美的跨平臺(tái)系統(tǒng)大大提高了不同平臺(tái)移植的工作效率。同時(shí)U3D還具備高度集成的系統(tǒng),以及優(yōu)秀的用戶交互操作界面,使得用戶能夠輕易入手該軟件創(chuàng)建自己的工程。其中五個(gè)視圖框架Project(存放資源文件)、Hierarchy(放置游戲?qū)ο螅cene(預(yù)覽編輯界面)、Game(游戲運(yùn)行結(jié)果)、inspector(查看對象的信息)合理放置并且多利用編輯器的快捷鍵可以使工作效率得到顯著的提高。以上所說的都是U3D比較表面的東西,現(xiàn)如今U3D在不斷的優(yōu)化,引入了燈光、地形、動(dòng)畫、渲染、粒子系統(tǒng)、可編程shader、物理系統(tǒng)等等。而引擎支持的語言為C#、javascript、boo三種腳本語言,其中C#由于優(yōu)秀的性能使得官方對其優(yōu)化力度也較高,所以大多數(shù)使用者選擇了C#。Unity3D常用函數(shù)由于U3D的高度集成性,在實(shí)現(xiàn)功能時(shí),常??梢越栌肬3D提供的函數(shù)來完成,可以通過繼承和引用命名空間的方式來獲取函數(shù),同時(shí)也可以通過繼承重載函數(shù),我們可以通過進(jìn)入函數(shù)內(nèi)部結(jié)構(gòu)查看內(nèi)置函數(shù)的說明。而U3D不像使用Vs編寫程序一樣,需要從Main函數(shù)入口進(jìn)入運(yùn)行,只需要引用UnityEngine命名空間并繼承MonoBehavior腳本并掛載到場景物體上運(yùn)行時(shí)內(nèi)部就會(huì)不斷迭代以下的生命函數(shù)REF_Ref25684\w[4]:Awake():物體初始化時(shí)調(diào)用,無論是否被激活。Start():晚于Awake()執(zhí)行,同時(shí)需要激活物體。OnEnable():每次激活該物體都會(huì)執(zhí)行一次,適用于每次打開的物體的初始化。Update();每幀都會(huì)調(diào)用一次,幀率是不穩(wěn)定的,對標(biāo)的為FixedUpdate(),區(qū)別在于FixedUpdate是固定幀,同時(shí)可以通過Application.targetFrameRate對游戲幀數(shù)進(jìn)行鎖定。LateUpdate():在Update(),后執(zhí)行,用于比如相機(jī)渲染等需要最后刷新的函數(shù)執(zhí)行。DisEnable():每次關(guān)閉物體使用一次,通過使用gameobject.Setive來控制物體的開關(guān)觸發(fā)。另外還還有些常用的函數(shù):OnTriggerEnter():需要碰撞體組件并且開啟Trigger模式,當(dāng)有剛體(Rigidbody)組件的物體進(jìn)入該物體使則會(huì)一直調(diào)用里面的函數(shù)。OnCollisionEnter():和OnTriggerEnter():不同,兩個(gè)都需要碰撞體和剛體,碰撞則觸發(fā)一次OnCollisionEnter2D():同OnCollisionEnter(),只是為二維對象。OnTriggerEnter()、OnTriggerStay()、OnTriggerExit()為一組,分別代表進(jìn)入、保持進(jìn)入、離開,只有Stay會(huì)一直觸發(fā),其他的均自觸發(fā)一次。每一個(gè)在引擎內(nèi)新建的腳本范本都會(huì)繼承和引用基類,在制作一些類似節(jié)點(diǎn)的腳本,或者結(jié)構(gòu)體等不需要再周期內(nèi)調(diào)用的函數(shù),可以自行去掉節(jié)省資源,后期可通過GC內(nèi)存管理清理不必要的內(nèi)存。2.1.3GUI(Unity3D自帶用戶圖形界面)本次游戲的制作使用引擎自帶的UGUI進(jìn)行UI界面的開發(fā),GUI是圖形用戶界面的簡稱,又叫圖形用戶接口。由于UI界面的存在,用戶不需要太高的專業(yè)性,做到了將技術(shù)性隱藏起來,同時(shí)增加了美觀性。通過使用UGUI可以簡單快捷的添加封裝好的各類界面元素,在創(chuàng)建完畢時(shí)候,引擎會(huì)實(shí)例化功能定義,而腳本中只需要獲取并且引用即可修改其中的資源信息,相對于遠(yuǎn)古版本的OnGUI(U3D自帶的腳本實(shí)現(xiàn)UI界面),顯著的提高了編輯速度以及客觀性,同時(shí)后期由于控件封裝的功能,可以使后期的修改位置角度或圖片等元素十分快捷,后期跨平臺(tái)或改變分辨率后對于空間的調(diào)整也不至于那么麻煩,極大的減少了開發(fā)時(shí)間以及設(shè)計(jì)的代碼量。2.1.4物理引擎及其他系統(tǒng)物理引擎是通過剛性物體賦予真實(shí)的物理屬性的方式來計(jì)算運(yùn)動(dòng)、旋轉(zhuǎn)和碰撞反映。如今的游戲以3d游戲?yàn)橹髁髭厔?,而物理系統(tǒng)也成為了游戲的不可或缺要素,可以說一個(gè)開發(fā)者能將物理引擎完美融入到游戲性,那么這個(gè)游戲必將成為游戲中的佼佼者。雖說物理系統(tǒng)可以通過自己編程來實(shí)現(xiàn),而對于初窺門徑的開發(fā)者來說,無疑是舉步為艱。而U3D為開發(fā)者提供了一系列物理組件,讓開發(fā)者不需要深入了解原理即可初步使用組件構(gòu)架出物理法則世界。無獨(dú)有偶,單單有物理系統(tǒng)是無法讓玩家沉浸其中,U3D提供了譬如地形、粒子、著色器、音效、動(dòng)畫機(jī)、材質(zhì)球、音效、貼圖、智能導(dǎo)航等等組件,使得初學(xué)乍練的開發(fā)者能滿懷熱情去探索游戲世界。2.1.5DoTween插件DOTween是一款針對于Unity開發(fā)的快速,高效兼顧類型安全的面向?qū)ο蟮拿赓M(fèi)動(dòng)畫引擎,針對C#用戶進(jìn)行了開源優(yōu)化,具有大量提高效率的功能。因?yàn)橐磺卸急痪彺娌⑶抑赜茫苊饬藷o用的GC分配,實(shí)現(xiàn)同時(shí)兼顧速度與效率。當(dāng)前開發(fā)團(tuán)隊(duì)更新了更為專業(yè)和高性能的進(jìn)階收費(fèi)版本,但本次游戲我們僅需在Unity商店下載免費(fèi)版本足以使用。通過本插件可以方便快捷的制作補(bǔ)間動(dòng)畫。不論是顏色、位置或者大小,在引入插件命名空間后直接調(diào)用物體的tranform組件即可輕易的調(diào)用函數(shù)實(shí)現(xiàn)動(dòng)畫。由于其應(yīng)用廣、邏輯易用、自由度高等特點(diǎn),已經(jīng)成為了每個(gè)使用Unity的新手最為熱門的入門插件之一。2.2C#開發(fā)語言C#是微軟公司發(fā)布的一種面向?qū)ο蟮?、運(yùn)行于.NET
Framework和.NET
Core(完全開源,跨平臺(tái))之上的高級(jí)程序設(shè)計(jì)語言。C#在不損失C/C++原有強(qiáng)大的功能和編寫的豐富類庫的前提下,能夠讓使得C++程序員可以高效的開發(fā)程序。C#是C的衍生,因而與C/C++具有著極大相似性,意味著了解類似語言的開發(fā)者可以快速的轉(zhuǎn)向C#。C#并不同于LUA、PYTHON具備跨平臺(tái)的特性,所以Unity殷勤通過Mono虛擬機(jī)將代碼實(shí)時(shí)編譯或者預(yù)先編譯到原生代碼實(shí)現(xiàn)移植到非Windows平臺(tái)的。選擇該語言,是因?yàn)镃#在網(wǎng)絡(luò)開發(fā)方面成績很優(yōu)秀、同時(shí)相對于動(dòng)態(tài)語言js更加穩(wěn)定,具備優(yōu)秀的類庫,同時(shí)U3D開發(fā)團(tuán)隊(duì)也更傾向?qū)τ贑#進(jìn)行優(yōu)化。2.3VisualStudioCode軟件Visual
Studio
Code軟件是微軟公司于2015年4月30日在Build開發(fā)者大會(huì)上正式推出的一款輕量級(jí)的跨平臺(tái)源代碼編輯器。使用該軟件進(jìn)行代碼的編寫可以使系統(tǒng)資源占用大幅度減少,同時(shí)最為人稱道的是他的極其強(qiáng)大的拓展性,,使得每個(gè)用戶都能夠找到自己想要的大部分功能。我最終選擇該軟件進(jìn)行編程的原因是因?yàn)槠鋬?nèi)嵌的小地圖,信息預(yù)覽和使用詳情,同時(shí)支持全局替換,這對于后期的優(yōu)化以及調(diào)試有著巨大的便利性。美術(shù)資源設(shè)計(jì)3.1場景設(shè)計(jì)3.1.1地形繪制正如前文提到的Unity自帶了地形(Terrian)系統(tǒng),本次游戲地形的制作就是通過該系統(tǒng)創(chuàng)建而成。該組件該組件類似于Maya中使用置換貼圖實(shí)現(xiàn)變形高段數(shù)的多邊形平面,原理是通過中等多邊形密度的多邊形平面,再指定一張灰階圖作為高插圖,根據(jù)mesh各頂點(diǎn)對應(yīng)的灰度數(shù)值改變Y軸的高度形成高低起伏的地形。通過Create->3DObject->Terrain在Hierarchy面板創(chuàng)建對象(如圖4.1-1),該組件的Terrian屬性欄最上排有七個(gè)主要按鈕,除了最后一個(gè)設(shè)置按鈕,其他的都是以筆刷的形式繪制地形,簡單介紹一下功能REF_Ref26938\w\h[5]。圖3-1創(chuàng)建地形Raise
Lower
Terrain、Paint
Height、Smooth
Height
這三個(gè)選項(xiàng)
點(diǎn)擊后都會(huì)出現(xiàn)筆刷面板,通過自定義筆刷大?。˙rushSize)和明度(Opacity)和筆刷類型可自定義繪制的地形,通過鼠標(biāo)在地形上拖動(dòng)即可繪制,而同時(shí)按住Shift鍵時(shí)繪制會(huì)變成使地形下限,前提是在TerrainSettings中設(shè)置地形的高度。PaintHight可以直接刷出特定高度,按住shift鍵獲取某一點(diǎn)的高度,即可直接刷出一個(gè)平滑的水平面高度的平整地形SmoothHeight點(diǎn)擊該選項(xiàng)后使用筆刷可以平滑地形,使坡度不會(huì)顯得突兀。Paint
Texture、Place
Trees、Place
Details這三個(gè)選項(xiàng)都需要自定義貼圖或者物體,根據(jù)順序起到的作用分別為在地形表面繪制貼圖、添加大型物體(通常用來做樹)、添加細(xì)節(jié)物體(如草叢、花),自定義添加物體需要需要在Textures/Trees/details欄中點(diǎn)擊編輯按鈕,再選擇對應(yīng)的資源即可直接在地圖中刷出物體,十分便捷,同時(shí)可以設(shè)置透明度改變刷出物的密度(如圖3-2)。
圖3-2添加編輯物體3.1.2添加風(fēng)塵效果完成了地形的繪制后,我們在場景中添加風(fēng)塵的效果,提高游戲的沉浸度和浸入感。首先制作一個(gè)風(fēng)塵粒子效果15,Unity中同樣集成了粒子系統(tǒng),在Hierarchy面板創(chuàng)建一個(gè)ParticelSystem,打開Inspector欄可以看到許多的選項(xiàng),簡單介紹一下我使用到的屬性REF_Ref26990\w\h[6]。(如圖3-3)圖3-3粒子效果基本屬性:其中包括粒子的動(dòng)畫時(shí)間、是否循環(huán)、發(fā)射速度和角度,顏色和最大粒子數(shù)等屬性,由于風(fēng)塵的凌亂我將發(fā)射角度和速度以及顏色各屬性設(shè)置在了一個(gè)區(qū)間內(nèi)隨機(jī)。Emission:控制發(fā)送速率,會(huì)影響粒子數(shù)量。Shape:控制發(fā)射場的形狀,這里設(shè)置為Box。Coloroverlifetime:控制生命周期內(nèi)顏色變化,可多個(gè)顏色混合或取隨機(jī)值。Rotationoverlifetime:控制生命周期內(nèi)的角度變化,可多個(gè)角度混合或取隨機(jī)值。Renderer:可以改變粒子的渲染材質(zhì)或者切換網(wǎng)格體等一系列渲染參數(shù)。為了場景中的物體受到風(fēng)的影響,我們在地形下添加風(fēng)場(WindZone),配置了風(fēng)場效果后,場景內(nèi)的樹會(huì)根據(jù)風(fēng)場的方向和速度搖曳。(如圖3-4)圖3-4添加風(fēng)場后的場景效果3.1.3添加建筑物地形制作和風(fēng)塵效果實(shí)現(xiàn)后,我們將房子模型預(yù)設(shè)體放置于場景中,為不可通過的物體(如墻、柵欄)添加對應(yīng)的碰撞體(不規(guī)則的模型可用MeshCollider啟動(dòng)convex屬性,網(wǎng)格便會(huì)完美貼合于模型上),同時(shí)為所有門添加之前便寫好的交互腳本。在場景中選擇合適的位置添加敵人預(yù)設(shè)范圍和玩家出生點(diǎn),最終為所有的房子添加生存資源自動(dòng)生成器(創(chuàng)建一個(gè)Cube關(guān)掉渲染效果和碰撞器同時(shí)添加ItemSpawner腳本,如圖3-5)。圖3-5配置完畢的場景3.1.4添加水面動(dòng)效島嶼四周的水面以及島中的一些水池如果只是用單純的面片的話會(huì)顯得十分的死板,而讓水面有動(dòng)態(tài)的效果有兩種做法,一是通過修改面片的法線起到高低起伏的效果,二是通過著色器修改。而第二種方法由于節(jié)省大量的資源被大眾所提倡使用,這次我也通過這種方式實(shí)現(xiàn)水面的動(dòng)效。首先,我們要先明白著色器的渲染流水線有兩個(gè)比較重要的階段為頂點(diǎn)處理和像素處理,而并不改變定點(diǎn)的信息,所以主要針對的是像素程序的編寫。主要的思路就是主貼圖的uv坐標(biāo)隨時(shí)間改變,而在著色器中實(shí)現(xiàn)隨機(jī)的效果一般通過導(dǎo)入一張?jiān)朦c(diǎn)圖,根據(jù)獲取噪點(diǎn)圖的差值信息和原圖進(jìn)行疊加,最終輸出的結(jié)果就是為隨機(jī)波動(dòng)的圖像動(dòng)畫了,核心代碼和效果圖如下。REF_Ref25668\w\h[11]fixed4
f_deal
(v2f
i)
:
SV_Target
{
fixed4
bias
=
tex2D(_Noise,
i.uv+_Time.xy*_distortFactorTime);
half4
color
=
tex2D(_MainTex,
i.uv+bias.xy*_distortFactor);
return
fixed4(color.rgb,0.5f);
}
圖3-6著色器處理后的水面3.2UI(用戶交互界面)設(shè)計(jì)UI面板分為游戲面板:背包面板、小地圖大圖面板、玩家游戲信息面板(指針、擊殺信息、準(zhǔn)心瞄準(zhǔn)鏡、血量能量條、子彈情況、倒計(jì)時(shí)、存活數(shù)量、公告信息)以及游戲系統(tǒng)面板:勝負(fù)界面、游戲菜單界面。(如圖3-6)圖3-6游戲UI的層級(jí)分布所有需要開關(guān)的UI面板都可以通過掛載PanelInstance這個(gè)單例腳本,同時(shí)在該腳本中引用了Dotween插件,在OnEnbale中使用了插值動(dòng)畫,使每次打開面板時(shí)能夠?qū)崿F(xiàn)變大逐漸呈現(xiàn)的插值動(dòng)畫效果,再在游戲初始化時(shí)獲取所有的交互面板到面板管理器中PlayerHUDCanvas(PanelsManager)。//利用DG實(shí)現(xiàn)過場動(dòng)畫效果
public
void
OnEnable(){
this.transform.localScale
=
Vector3.zero;
this.GetComponent<Image>().color
=
new
Color(255,255,255,0);
this.transform.DoScale(new
Vector3(1,1,1),0.5f);
this.GetComponent<Image>().DoColor(new
Color(255,255,255,0),0.5f);
}
為了方便各種情況的調(diào)用,腳本中設(shè)計(jì)了多種情形下打開和關(guān)閉腳本的方式,但總歸都是通過數(shù)組和集合再利用循環(huán)進(jìn)行面板的切換。在PlayerHUDCanvas中才是具體的控制面板的參數(shù)改變,主要為血量的變化、通知信息的刷新、背包面板信息的改變給控制器腳本和玩家控制腳本實(shí)現(xiàn)了外界的接口。根據(jù)圖4.2-1的Inspector屬性欄可以清楚的看到引用的物體信息。public
PanelInstance[]
Pages;
public
PanelInstance
currentPanel;
//
關(guān)閉所有腳本
public
void
CloseAllPanels
()
{
if
(Pages.Length
<=
0)
return;
for
(int
i=0;
i<Pages.Length;
i++)
{
Pages[i].OpenPanel
(false);
if(Pages
[i].isActiveAndEnabled){
StartCoroutine
(DisablePanelDeleyed
(Pages
[i]));
}
}
}
//根據(jù)名字打開相應(yīng)的腳本
public
void
OpenPanelByName
(string
name)
{
PanelInstance
page
=
null;
for
(int
i=0;
i<Pages.Length;
i++)
{
if
(Pages
[i].name
==
name)
{
page
=
Pages
[i];
break;
}
}
if
(page
==
null)
return;
page.PanelBefore
=
currentPanel;
currentPanel
=
page;
CloseAllPanels
();
page.OpenPanel
(true);
}
UI的框架分為PanelInstance->PanelsManager(個(gè)人常用的ui框架)->PlayerHUDCanvas作為一個(gè)主題,同時(shí)將單例各面板分派給獨(dú)立的腳本控制。例如游戲結(jié)束界面的數(shù)據(jù)顯示以及擊殺信息顯示而PlayerHUDCanvas在游戲初始化時(shí)就進(jìn)行實(shí)例,綁定到游戲總控制器FgameManager中集中控制,在需要執(zhí)行ui事件時(shí)只需要調(diào)用FgameManager即可
這樣的調(diào)用方式調(diào)用入口統(tǒng)一,同時(shí)也減少了所有的代碼聚集在一個(gè)腳本中防止后期調(diào)試和修復(fù)bug的困難。
第四章游戲功能設(shè)計(jì)以及實(shí)現(xiàn)4.1游戲基本規(guī)則及功能設(shè)計(jì)本次開發(fā)的游戲,玩家通過鼠標(biāo)和鍵盤進(jìn)行角色的操控。在游玩的過程中,玩家可以進(jìn)行人稱視角的切換、通場景的物體進(jìn)行交互、行走跳躍、同時(shí)還可以改變進(jìn)行的狀態(tài),可以走跑蹲趴,令玩擁有豐富的進(jìn)攻方式和隱蔽自己的方式。在游戲的一開始玩家會(huì)在出生島等待,繼而會(huì)到飛機(jī)上跳傘到達(dá)軍事演練地點(diǎn),通過搜集散落在場景中的軍事物資,通過靈活多變的方式淘汰對手,在過程中,會(huì)逐漸縮減安全范圍,當(dāng)最后一個(gè)人存活時(shí),游戲方能結(jié)束。每當(dāng)一定的時(shí)間間隔,都會(huì)生成具有肥沃物資的空投予于玩家拾取REF_Ref27111\w[3]REF_Ref27118\w[2]。總結(jié)規(guī)則后可以將游戲的主要功能分為三部分:實(shí)現(xiàn)玩家對游戲角色的控制、在玩家系統(tǒng)的基礎(chǔ)上添加敵人AI、實(shí)現(xiàn)控制整個(gè)游戲流程的總控制器。如下圖4-1所示。圖4-1游戲框架圖4.2玩家系統(tǒng)4.2.1玩家的輸入圖4-2玩家輸入按鍵示意圖如上圖所示,PlayerInputController腳本負(fù)責(zé)接收玩家所有的輸入值,并且調(diào)用相應(yīng)的函數(shù)去實(shí)現(xiàn)對應(yīng)輸入的功能,這種歸納到一個(gè)腳本控制的做法對于后期的調(diào)試有著極大的幫助。如下圖所示,數(shù)字1-5代表著對應(yīng)類型武器的切換,而WSAD鍵用以控制玩家角色的移動(dòng),Tab鍵控制背包的開關(guān),C鍵用于改變玩家的行走姿態(tài),V鍵用以控制玩家視野的改變,M鍵控制大地圖的打開,而F鍵控制的則是與場景中各種物體的交互,譬如打開門、拾取物體、離開飛機(jī)等事件。而鼠標(biāo)左鍵控制玩家進(jìn)行攻擊事件,右鍵打開瞄準(zhǔn)功能(需武器本身擁有此功能接口),同時(shí)鼠標(biāo)的移動(dòng)控制視角的旋轉(zhuǎn)。代碼中可以通過Input.Get..系列腳本可以監(jiān)聽相應(yīng)的按鍵事件,GetAxis()以及GetButton()函數(shù)對應(yīng)的鍵值可以在編輯器Edit->ProjectSetting->Input中修改相應(yīng)的監(jiān)聽鍵值,而GetKeyDown(KeyCode)可以直接監(jiān)聽傳入的鍵是否被按下。4.2.2玩家的生成無論是玩家、敵人亦或是隨機(jī)刷新的軍事物資生成的原理都是相同的,獲取已經(jīng)配置好的預(yù)設(shè)體,然后使用Instantiate()傳入需要生成的物體、位置以及角度即可生成。而為了保持相對的隨機(jī),我們選擇將物體的生成控制在一個(gè)范圍內(nèi)隨機(jī)獲取生成位置。#if
UNITY_EDITOR
using
UnityEditor;
#endif
void
OnDrawGizmos()
{
#if
UNITY_EDITOR
Gizmos.color
=
Color.Green;
Gizmos.DrawSphere(transform.position,
2);
Gizmos.DrawWireCube(transform.position,
this.transform.localScale);
Handles.Label(transform.position,
"玩家生成區(qū)域");
#endif
}
為了方便觀察區(qū)域的位置和移動(dòng),可以引入U(xiǎn)nityEditor,調(diào)用OnDrawGizmos()并編寫Gizmos.DrawWireCube()即可在編輯器Scene視圖繪制出相應(yīng)范圍的正方體范圍。(此處使用預(yù)處理器命令判斷防止項(xiàng)目導(dǎo)出時(shí)出現(xiàn)錯(cuò)誤)如下圖4-3所示,綠、紅、藍(lán)分別表示玩家、敵人以及物資的生成區(qū)域。圖4-3角色生成區(qū)域public
Vector3
SpawnPoint
()
{
return
CheckGroundHeight(this.transform.position
+new
Vector3(
Random.Range
(-(int)(this.transform.localScale.x
/
2.0f),(int)(this.transform.localScale.x
/
2.0f)),
0,
Random.Range
(-(int)(this.transform.localScale.z
/
2.0f),
(int)(this.transform.localScale.z
/
2.0f)))
);}
//檢測腳下的地面高度
Vector3
CheckGroundHeight(Vector3
srcPos)
{
RaycastHit
hit;
if
(Physics.Raycast
(position,
-Vector3.up,
out
hit,
1000.0f))
{
return
hit.point
+
Offset;
}
return
srcPos;
}
配置完之后,在需要生成物體時(shí),使用Random.Range()返回x/z軸平面一個(gè)隨機(jī)的點(diǎn),由于Unity默認(rèn)的游戲?qū)ο蟮膌ocalScale為1,而當(dāng)我們在設(shè)置區(qū)域大小的時(shí)候正是修改的此值,因此這里localScale實(shí)際上就等于一個(gè)長度的獲取。同時(shí)為了物體能正確的顯示在地面(由于山體坡度的不統(tǒng)一需要實(shí)時(shí)獲?。?,需要獲取一個(gè)正確的高度點(diǎn),將獲得的隨機(jī)點(diǎn)向下發(fā)射一次射線,當(dāng)檢測到碰撞信息再加上一個(gè)向上的單位向量Vector3.Up即可保證該高度恰巧處于地面之上。首先需要定義一個(gè)RaycastHit射線,然后調(diào)用Physics.Raycast()初入發(fā)射起點(diǎn)和方向以及長度,即可將射線碰撞的信息存入Hit中,而Hit.Point就是射線檢測到的地面坐標(biāo)點(diǎn)。此時(shí)只需要調(diào)用Instantiate()傳入物體、位置。角度即可生成相應(yīng)的物體。Instantiate(gameObject,SpawnPoint(PlayerSpawner.tranform,position),Quaternion.identity)
;
4.2.3動(dòng)畫系統(tǒng)在第三人稱游戲中需要十分多的動(dòng)畫過度,在Unity中過度動(dòng)畫需要先對動(dòng)畫機(jī)進(jìn)行配置,如圖,首先將所有的人物動(dòng)畫放置到動(dòng)畫機(jī)中,并按照相應(yīng)的動(dòng)畫轉(zhuǎn)化條件將動(dòng)畫連接起來并設(shè)置相應(yīng)的變量值,然后在Conditions設(shè)置觸發(fā)動(dòng)畫間的觸發(fā)條件,如下圖4-4所示。public
override
void
PlayAttackAnimation(bool
attacking,
int
attacktype)
{
if
(animator)
{
if
(attacking)
{
animator.SetTrigger("Shoot");
}
animator.SetInteger("Shoot_Type",
attacktype);
}
base.PlayAttackAnimation(attacking,
attacktype);
}圖4-4動(dòng)畫機(jī)系統(tǒng)配置接下來只需要在代碼中獲取動(dòng)畫機(jī)Animator,并且相應(yīng)的變量類型調(diào)用設(shè)置函數(shù),傳入對應(yīng)的變量名和數(shù)值即可對動(dòng)畫機(jī)的狀態(tài)進(jìn)行改變。如上述代碼則是確認(rèn)存在動(dòng)畫機(jī)的情況下,設(shè)置Trigger類型的變量Shoot為觸發(fā)狀態(tài),設(shè)置Shoot_Typed的int變量為對應(yīng)的狀態(tài)。4.2.4場景交互的實(shí)現(xiàn)游戲中需要許多需要交互的東西,如圖所示,當(dāng)玩家屏幕對準(zhǔn)物體時(shí),會(huì)顯示物體的相關(guān)信息,其他處于可交互狀態(tài)的情況下也會(huì)出現(xiàn)可交互的示意文字。這意味著在游戲中會(huì)按照一定頻率對屏幕中心物體進(jìn)行檢測,當(dāng)為可交互的物體時(shí)而對玩家進(jìn)行反饋,而按下交互鍵使則執(zhí)行對應(yīng)的操作REF_Ref27193\w[7]。public
void
Yzw_Checking()
{
float
raySize
=
2.5f;
Vector3
origin
=
PlayerView.FPSCamera.RayPointer.position;
Vector3
direction
=PlayerView.FPSCamera.RayPointer.forward;
RaycastHit[]
casterhits
=
Physics.RaycastAll(origin,direction
,
raySize);
for
(int
i
=
0;
i
<
casterhits.Length;
i++)
{
if
(casterhits[i].collider)
{
RaycastHit
hit
=
casterhits[i];
hit.collider.SendMessage("GetInfo",
SendMessageOptions.DontRequireReceiver);
}
}
}
這里又再一次運(yùn)用到了射線,調(diào)用的方式相同,此時(shí)的射線發(fā)射點(diǎn)為相機(jī)正中心的位置,而方向也為相機(jī)的正前方,即玩家的屏幕中心。在Update()中不斷刷新的射線一旦檢測到有可交互的物體,就會(huì)通過獲取的碰撞體發(fā)送調(diào)用GetInfo()函數(shù)的信息,這里發(fā)送信息的方法為SendMessage(),首先需要傳入調(diào)用的函數(shù),后面為設(shè)置接受者是否需要為監(jiān)聽狀態(tài),而SendMessageOptions.DontRequireReceiver表示不需要為接受者狀態(tài)。(如圖4-5)public
override
void
GetInfo()
{
YZW.Hud.ShowInfo("按下“F”開門",
this.transform.position);
}
public
void
ShowInfo(string
info,
Vector3
position)
{
if
(Info
!=
null)
{
isShowinfo
=
true;
Info.gameObject.SetActive(true);
RectTransform
inforec
=
Info.GetComponent<RectTransform>();
inforec.anchoredPosition
=
GetWorldSpaceUIposition(position);
Info.text
=
info;
timeInfo
=
Time.time;
}
}
圖4-5場景交互以門的反饋信息為例,如上圖4-5所示,當(dāng)可交互物體被檢測到時(shí)反饋本身的信息到玩家的交互界面控制器HudManager中,而HudManager中的ShowInfo()會(huì)將場景中的提示文本的游戲?qū)ο蟠蜷_,在通過GetWorldSpaceUIposition()將物體的世界坐標(biāo)轉(zhuǎn)化為屏幕坐標(biāo)以確保文本在物體中心位置,最后在替換文本。同理,當(dāng)玩家按下交互鍵時(shí)可以同樣發(fā)射一條射線確認(rèn)當(dāng)前的物體可交互,并且請求調(diào)用該物體腳本中的交互函數(shù),則可以進(jìn)行玩家角色和場景的交互。4.2.5背包系統(tǒng)人物需要和場景內(nèi)的物體交互,主要行為是將場景內(nèi)的演習(xí)資源放入背包中,將物品丟棄,武器裝彈消耗背包內(nèi)物體。由于只有當(dāng)玩家距離交互物體到一定距離并且對準(zhǔn)物體才能進(jìn)行交互,所以需要一直檢測玩家是否檢測到了交互物體,通過發(fā)射射線對當(dāng)前視角中心的物體進(jìn)行檢測,當(dāng)玩家有物體時(shí),將物體信息傳入總控制器中的ui部分并且顯示出來提示玩家可以進(jìn)行交互。當(dāng)玩家按下交互鍵時(shí),則發(fā)送信息,如果是物體的話則將物體存入背包中。當(dāng)存入物品過多超過了背包的容量想要丟棄部分不需要的物資時(shí),只需點(diǎn)擊UI面板中背包面板中想要丟棄的物品即可丟出。當(dāng)武器進(jìn)行換彈時(shí),會(huì)讀取當(dāng)前槍支的最大容量和當(dāng)前容量計(jì)算出需要消耗的子彈數(shù)量進(jìn)行填充。(如圖4-6)圖4-6背包系統(tǒng)在游戲中搜集物資需要對物體進(jìn)行存儲(chǔ)、丟棄以及使用。而物品的存儲(chǔ)需要將物品以及數(shù)量一一對標(biāo),同時(shí)由于物體的特性不同,需要定義類型來區(qū)分。public
void
AddSmToBag(ItemData
sm,int
count)
{
for
(int
i
=
0;
i
<
ItemsList.Length;
i++)
{
if
(sm.ItemID
==
ItemsList[i].ItemID)
{
ItemsList[i].index+=count;
}
}
ItemsList.Add(sm);
}
由于物品的特性不同,通過枚舉將所有的類型列舉出來。每個(gè)物體具備多個(gè)特性,所以這里將物體的各項(xiàng)屬性編寫成一個(gè)ItemCollector類,方便我們將其存入列表中。public
class
ItemCollector
{
public
ItemData
Item;
public
int
count;
public
int
NumTag
=
-1;
public
bool
isOpen;
public
int
Shortcut
=
-1;
public
int
EquipIndex
=
-1;
public
int
EquipMod
=
-1;
public
bool
InUse
=
false;
public
int
InventoryIndex;
public
int
ItemIndex;
}
public
void
LoadSmData(ItemData
sm,int
count)
{
for
(int
o
=
0;
o
<
ItemsList.Length;
o++)
{
if
(sm.ItemID
==
ItemsList[o].ItemID)
{
ItemsList[o].index+=count;
}
}
ItemsList.Add(sm);
}
在對物體進(jìn)行存儲(chǔ)時(shí),通過For循環(huán)確認(rèn)列表是否以及有相同物體,如果列表中已經(jīng)存在該物體,則直接將加入的物體數(shù)量疊加到列表中物體,而如若沒有該物體,則添加該物體到列表中。丟棄物品時(shí)則相反,由于丟棄的數(shù)量不一定為全部,所以需要對物體的數(shù)量進(jìn)行判斷,如果丟棄后數(shù)量為0時(shí)則移除該物體。4.2.6音效控制在Unity中使用音頻需要用到AudioSource和AudioClip兩個(gè)組件,AudioSource類似于一個(gè)播放器,而AudioClip則是用來掛載音源。通過調(diào)用AudioSource的PlayOneShot()方法即可播放音源,與Play()方法不同,playOneShot就是為了解決播放多種和多次音效的問度題而生的(個(gè)人觀點(diǎn)),這函數(shù)不管你目前有沒有正在播放音效,它都會(huì)另起爐灶播放指定的音效,并且不會(huì)打斷當(dāng)前正在播放的音效。if
(delay
>=
Delay)
{
audios.PlayOneShot(FoodSteps[Random.Range(0,
FoodSteps.Length)]);
delay
=
0;
}
if
(delay
<
Delay)
{
//根據(jù)移動(dòng)速度改變音軌時(shí)間
delay
+=
character.MoveVelocity.magnitude
*
Time.deltaTime;
}
通過獲取當(dāng)前角色的移動(dòng)速度來控制音頻的播放速率,速度越快,則音頻結(jié)束的速度越快,為了腳步看起來自然,這里我導(dǎo)入了三個(gè)音頻隨機(jī)播放,如下圖4-7所示。圖4-7音頻控制4.2.7人物的基本移動(dòng)移動(dòng)和跳躍可以說是3d游戲中最基礎(chǔ)的移動(dòng),在Unity中使用物理系統(tǒng)進(jìn)行最基礎(chǔ)的移動(dòng)方式主要通過給予玩家物體剛體組件,通過施加力來控制玩家的移動(dòng)和跳躍,而前文我們提到的加速則是通過增大施加力的數(shù)值達(dá)到更快的速度。角色控制器是官方基于剛體設(shè)計(jì)的專門用于角色的基本控制的組件,如圖4-8所示,具有角色移動(dòng)主要的幾項(xiàng)屬性,本次我們在此組件的基礎(chǔ)上編寫玩家的移動(dòng)和跳躍時(shí)間。圖4-8角色控制器組件角色控制器中有編寫好的移動(dòng)函數(shù),只需要傳入移動(dòng)的方向和數(shù)值即可進(jìn)行移動(dòng)。跳躍的本質(zhì)是向上人體對地面施加一個(gè)力,反作用力將人體推向天空,而在地心引力的作用下人體速度逐漸衰減然后下降到地面,因此我們需要?jiǎng)?chuàng)建一個(gè)模擬的重力場,并給予物體一個(gè)向上的加速度,并實(shí)時(shí)計(jì)算在重力的情況下速度的衰減變化,通過isGrounded檢測是否回到地面來控制跳躍狀態(tài)的開關(guān)。
public
CharacterController
_myBody;
public
float
_runSpeed=
1;
public
bool
_isJump
=
false;
public
float
_jumpSpped
=
3;
public
float
_gravity
=
1;
public
float
_Vspeed
=
0;
void
Update
()
{
_myBody.Move(new
Vector3(Input.GetAxis("Vertical"),_Vspeed,Input.GetAxis("Horizontal"))*_runSpeed);
if
(Input.GetButton("Jump")
&&
!_isJump)
{
_isJump
=
true;
_Vspeed
=
_jumpSpped;
}
if
(_isJump)
{
_Vspeed
-=
_gravity
*
Time.deltaTime;
//人物碰撞地面了
if
(_myBody.isGrounded)
_isJump
=
false;
}
}
4.2.8人物戰(zhàn)斗系統(tǒng)人物從拾取到槍支后進(jìn)行攻擊時(shí)主要是沿著攝像頭的正前方創(chuàng)建一個(gè)子彈物體,當(dāng)物體生成后機(jī)會(huì)開始沿著子彈的正前方不斷的刷新自身的位置。public
void
Update(){
this.transform.position
+=
this.transform.forward
*
Speed
*
Time.deltaTime;
}
當(dāng)子彈命中敵人或地面以及到達(dá)銷毀時(shí)間時(shí)就會(huì)刪除該物體,這里直接用Destory函數(shù)銷毀物體,第二個(gè)參數(shù)代表延遲的時(shí)間。public
void
Start(){
GameObject.Destroy(this.gameObject,
lifeTime);
}
當(dāng)玩家進(jìn)行射擊時(shí),為了還原槍械后坐力的效果,這里采用了Dotween插件中的Punching函數(shù)對相機(jī)的角度進(jìn)行上移,該函數(shù)可以實(shí)現(xiàn)從角度到設(shè)定角度的移動(dòng)并且回彈,這個(gè)效果十分迫近現(xiàn)實(shí)的后坐力,同時(shí)Dotween優(yōu)秀的插值計(jì)算使得我們動(dòng)態(tài)修改攝像機(jī)的位置與角度也不會(huì)影響到回彈操作的進(jìn)行,代碼如下。transform.DOPunchRotation(new
Vector3(-1,
0,
0),0.3f,
2,
0.1f);
//傳入的參數(shù)分別表示:移動(dòng)方向(向上)、動(dòng)畫時(shí)間、震動(dòng)次數(shù)。最后參數(shù)不為0時(shí),會(huì)把你賦的值乘上一個(gè)參數(shù),作為你運(yùn)動(dòng)方向反方向的點(diǎn),物體在這個(gè)點(diǎn)和目標(biāo)點(diǎn)之間運(yùn)動(dòng)
而玩家受到攻擊時(shí),會(huì)調(diào)用函數(shù)對自身的血量進(jìn)行修改,并且反饋到屏幕。主要的流程和前文一樣,都是通過調(diào)用交互界面管理器進(jìn)行反饋。(如圖4-9)圖4-9受擊效果4.3敵人AIAI敵人需要模擬真實(shí)玩家的效果,由于敵人和玩家之間的代碼可以大量的復(fù)用,所以只需要對敵人的狀態(tài)能夠起到根據(jù)情況能自主的進(jìn)行轉(zhuǎn)換即可,根據(jù)功能的需求,機(jī)器人具備的狀態(tài)有,在原地站立、尋找敵人的狀態(tài)、移動(dòng)到安全區(qū)的狀態(tài)。促使敵人行為狀態(tài)的改變元素有內(nèi)外之分,外因?yàn)榘l(fā)現(xiàn)了敵人(玩家或其他AI)時(shí)則會(huì)進(jìn)入戰(zhàn)斗狀態(tài)或者安全區(qū)縮小則AI會(huì)往安全區(qū)前進(jìn),內(nèi)在為設(shè)置的刷新時(shí)間到了,隨機(jī)獲取新的狀態(tài)REF_Ref27193\w[7]REF_Ref27271\w[8]。首先先設(shè)定AI的發(fā)現(xiàn)距離和獲取武器攻擊距離,三個(gè)狀態(tài)直接會(huì)互相轉(zhuǎn)換,譬如當(dāng)敵人處于原地待機(jī)狀態(tài)時(shí),發(fā)現(xiàn)了敵人或者定期刷新狀態(tài)的時(shí)間到了,那么敵人就會(huì)轉(zhuǎn)為攻擊或巡邏狀態(tài),而當(dāng)機(jī)器人處于無戰(zhàn)斗狀態(tài)時(shí),安全區(qū)縮小時(shí)機(jī)器人會(huì)往安全區(qū)的方向撤離。當(dāng)敵人處于戰(zhàn)斗狀態(tài)時(shí),當(dāng)敵人消失在視野中或者逃出了追擊距離,那么喪失目標(biāo)的機(jī)器人將會(huì)切換狀態(tài)進(jìn)入漫游或待機(jī)狀態(tài),如下圖4-10所示。圖4-10敵人行為邏輯在現(xiàn)如今游戲絕地求生中,機(jī)器人會(huì)進(jìn)入房子中搜集物資,看起來和旁人無疑,但早期的機(jī)器人是自動(dòng)生成生存物資的,為了降低游戲的復(fù)雜度,這里我將沿用其早期版本的用法。在機(jī)器人誕生之后一段時(shí)間后(給玩家收集物資的時(shí)間),則開始進(jìn)行對機(jī)器人物資的生成,包括防具以及武器,而這里敵人的子彈是無限的,因此敵人不需要重復(fù)再生成物資。TimeWait
=
ItemSets[i].NextTime
+
Random.Range(0,
ItemSets[i].NextTime
/
2)
if
(ItemSets[i].RandomEquipOne)
{
//隨機(jī)裝備一些物體
character.inventory.AddItemByItemData(ItemSets[i].Items[Random.Range(0,
ItemSets[i].Items.Length)],
1,
-1,
-1);
character.inventory.UpdateInventoryToAll();
}
else
{
for
(int
v
=
0;
v
<
ItemSets[i].Items.Length;
v++)
{
character.inventory.AddItemByItemData(ItemSets[i].Items[v],
1,
-1,
-1);
}
character.inventory.UpdateInventoryToAll();
}
}4.4游戲總控實(shí)現(xiàn)除開玩家和敵人,最為重要的就是整個(gè)游戲的自控系統(tǒng)。整個(gè)系統(tǒng)負(fù)責(zé)了游戲的進(jìn)程,以及除開人物的所有的元素控制。譬如游戲玩家進(jìn)入飛機(jī)、空投的丟落、安全區(qū)的縮進(jìn),游戲的勝負(fù)條件以及我們之前所說的機(jī)器人生成。4.4.1切換場景將戰(zhàn)斗場景和開始場景分割開,可以防止游戲一開始加載的資源過多導(dǎo)致的卡頓。首先需要將所有的場景添加到BuildingSetting中,不然在跳轉(zhuǎn)的時(shí)候會(huì)因找不到索引導(dǎo)致出錯(cuò)。UnityEngine.SceneManagement.SceneManager.LoadScene("battleground");
void
OnEnable()
{
UnityEngine.SceneManagement.SceneManager.sceneLoaded
+=
OnLevelFinishedLoading;
}
void
Awake
()
{
DontDestroyOnLoad
(this.gameObject);
}
上述代碼調(diào)用SceneManager.LoadScene(),將目標(biāo)場景的名字傳入函數(shù)中調(diào)用即可切換場景,此腳本一般還需要在Awake函數(shù)中聲明加載新場景時(shí)不銷毀,可以避免多個(gè)場景重復(fù)掛載,同時(shí)還可以通過對SceneManager.sceneLoad事件添加委托,即可在每次加載新場景的時(shí)候刷新設(shè)置為不銷毀物體的某種屬性。4.4.2生成物體場景控制器也負(fù)責(zé)各角色和物資的生成,生成敵人的方法類型,但為了保證敵人的隨機(jī)性,敵人的生成區(qū)域有多個(gè),因此生成時(shí)需要獲取場景中所有的敵人區(qū)域隨機(jī)生成。public
void
SpawnAI()
{
EnemySpawner
spawner
=
(EnemySpawner)GameObject.FindObjectOfType<EnemySpawner>();
if
(spawner)
{
spawner.MaxObject
=
YZW.gameManager.BotNumber;
AIs
=
spawner.Spawn(YZW.gameManager.BotNumber);
for
(int
i
=
0;
i
<
AIs.Length;
i++)
{
if
(AIs[i]
!=
null)
{
AICharacterShooterNav
ai
=
AIs[i].GetComponent<AICharacterShooterNav>();
if
(ai
!=
null)
{
ai.Fighting
=
false;
}
}
}
}
}
以上代碼通過FindObjectOfType獲取所有擁有EnemySpawner的游戲物體,并且根據(jù)之前設(shè)置的機(jī)器人數(shù)量BotNumber,生成對應(yīng)數(shù)量的敵人。在生成結(jié)束后將敵人的戰(zhàn)斗狀態(tài)打開,開始智能搜集物資的狀態(tài),物資的生成同理,參考有關(guān)玩家的生成。還有一種比較特殊的物體為飛機(jī)。用到飛機(jī)的場景是按時(shí)刷新的空投,由于第一次空降不需要空投所以設(shè)置了一個(gè)布爾進(jìn)行區(qū)分。
public
void
SpawnPlane(bool
drop,
Vector3
passingTo)
{
AirplaneSpawner
spawner
=
GameObject.FindObjectOfType<AirplaneSpawner>();
if
(spawner
!=
null)
{
Vector2
pos
=
Random.insideUnitCircle;
pos.Normalize();
pos
*=
spawner.transform.localScale.x;
pos
=
this.transform.position
+
new
Vector3(pos.x,
0,
pos.y)
+
Vector3.up;
GameObject
planeobj
=
Instantiate(AirplaneObject,
pos,
Quaternion.identity);
if
(planeobj
!=
null)
{
Debug.Log("生成飛機(jī)");
planeobj.transform.LookAt(passingTo
+
(Vector3.up
*
planeobj.transform.position.y));
Airplane
plane
=
planeobj.GetComponent<Airplane>();
if
(plane
!=
null)
{
plane.DropSupply
=
drop;
plane.SetDrop(passingTo);
}
}
}
}這里類似于生成敵人,也是獲取場景中的飛機(jī)生成點(diǎn)的游戲?qū)ο螅缓笸ㄟ^SpawnPoint()方法Random.insideUnitCircle返回一個(gè)單位圓的隨機(jī)向量,將向量標(biāo)準(zhǔn)化后乘于對應(yīng)的區(qū)域范圍即可獲取一個(gè)單元原邊緣的一個(gè)隨機(jī)點(diǎn)。在生成飛機(jī)物體后,根據(jù)生成的情況設(shè)置是否需要進(jìn)行空投的投放設(shè)置。4.4.3安全區(qū)控制 if
(DeadAreas.Length
>
currentArea)
{
LerpValue
=
0;
DeadArea
NextArea
=
DeadAreas[currentArea];
currentAreaDamage
=
NextArea.Damage;
Radius
=
NextArea.Radius;
if
(Time.time
>=
timeAreaTmp
+
NextArea.Time)
{
if
(!isEscape)
{
timeEscapeTmp
=
Time.time;
isEscape
=
true;
}
float
timing
=
1
-
(((NextArea.EscapeTime
+
timeEscapeTmp)
-
Time.time)
/
NextArea.EscapeTime);
if
(currentArea
>
0)
LerpValue
=
timing;
if
(Time.time
>
NextArea.EscapeTime
+
timeEscapeTmp)
{
if
(lastDeadArea)
{
positionTmp
=
CentreArea;
scaleTmp
=
new
Vector3(Radius,
SafeArea.transform.localScale.y,
Radius)
*
2;
}
if
(currentArea
>=
DeadAreas.Length
-
1)
return;
currentArea
+=
1;
isEscape
=
false;
timeAreaTmp
=
Time.time;
CentreArea
=
GetArea(CentreArea,
Radius
-
(DeadAreas[currentArea].Radius));
CmdStartNewArea(positionTmp,
scaleTmp,
currentArea);
if
(DeadAreas[currentArea].AirDrop)
SpawnPlane(true,
CentreArea);
}
}
else
{
float
timeLeft
=
(timeAreaTmp
+
NextArea.Time)
-
Time.time;
if
(timeLeft
<
60)
{
if
(Time.time
>=
broadcastTimpTmp
+
10)
{
{
Broadcast("距離安全區(qū)縮小還有
"
+
Mathf.Ceil(timeLeft)
+
"
秒",
3);
broadcastTimpTmp
=
Time.time;
}
}
}
}
damageUpdate();
}
if
(safeArea
&&
lastDeadArea)
{
safeArea.transform.position
=
CentreArea;
safeArea.transform.localScale
=
new
Vector3(Radius,
SafeArea.transform.localScale.y,
Radius)
*
2;
lastDeadArea.transform.position
=
Vector3.Lerp(positionTmp,
safeArea.transform.position,
LerpValue);
lastDeadArea.transform.localScale
=
Vector3.Lerp(scaleTmp,
safeArea.transform.localScale,
LerpValue);
}
安全區(qū)的縮小實(shí)際上是通過NextArea.Time(下個(gè)圈到達(dá)時(shí)間)結(jié)合timeAreaTmp(當(dāng)前區(qū)域時(shí)間)和Time.time(實(shí)際時(shí)間)已經(jīng)倒計(jì)時(shí)的判斷的,而每次時(shí)間達(dá)到之后會(huì)刷新所有有關(guān)該圈的數(shù)值,如下圖所示,當(dāng)前毒圈的傷害、下一個(gè)圈的距離、毒圈的縮小范圍。同時(shí)在即將到達(dá)縮圈時(shí)間前,會(huì)通過調(diào)用玩家的用戶交互界面提示圈即將縮小的事件。
第五章屏幕后效5.1選中效果由于游戲場景中物體繁多,有可能會(huì)出現(xiàn)部分疊加在一起的情況,為了能夠更加直觀明確的看出是否選中了當(dāng)前物體,加入一個(gè)物體描邊的效果提示。物體選中以輪廓提示,一般是通過修改材質(zhì)來實(shí)現(xiàn),但是由于物體過多,逐個(gè)修改材質(zhì)未免有些繁瑣,所以這里選擇用屏幕后處理的方式實(shí)現(xiàn)。這種做法需要一個(gè)額外的攝像機(jī)專門用來渲染輪廓,同時(shí)需要設(shè)定對象為對應(yīng)的Layer,在該層級(jí)的問題進(jìn)入描邊攝像機(jī)時(shí),即會(huì)對物體進(jìn)行處理,其本質(zhì)是對物體進(jìn)行模糊處理(兩次模糊、橫向縱向以此進(jìn)行高斯模糊),然后通過原始圖以及模糊圖計(jì)算出輪廓圖,最終混合采樣輪廓圖和原始圖進(jìn)行疊加再次輸出到視圖中。
//高斯模糊,兩次模糊,橫向縱向,使用pass0進(jìn)行高斯模糊
_mat.SetVector("_offsets",
new
Vector4(0,
samplerScale,
0,
0));
Graphics.Blit(renderTexture,
temp1,
_mat,
0);
_mat.SetVector("_offsets",
new
Vector4(samplerScale,
0,
0,
0));
Graphics.Blit(temp1,
temp2,
_mat,
0);
//如果有疊加再進(jìn)行迭代模糊處理
for(int
i
=
0;
i
<
iteration;
i++)
{
_mat.SetVector("_offsets",
new
Vect
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 二零二五年度訂制尺寸訂框安裝合同
- 2025年度物流企業(yè)合作投資與知識(shí)產(chǎn)權(quán)保護(hù)協(xié)議
- 二零二五年度旅游企業(yè)法人景區(qū)經(jīng)營權(quán)轉(zhuǎn)讓合同
- 2025年度股權(quán)激勵(lì)協(xié)議書-員工股權(quán)激勵(lì)與股權(quán)激勵(lì)計(jì)劃實(shí)施合同范本
- 二零二五年度紅薯種植技術(shù)培訓(xùn)與收購服務(wù)合同
- 關(guān)于業(yè)務(wù)合作的函件示例
- 家裝設(shè)計(jì)行業(yè)項(xiàng)目執(zhí)行標(biāo)準(zhǔn)
- 幼兒園教育服務(wù)合作框架協(xié)議
- 初中力學(xué)基礎(chǔ)實(shí)驗(yàn)課教案
- 公司辦公管理規(guī)章制度手冊
- 四川省既有居住小區(qū)改造技術(shù)標(biāo)準(zhǔn)
- 慢性血栓栓塞性肺動(dòng)脈高壓診斷與治療指南(2024版)解讀
- 2024年南京科技職業(yè)學(xué)院單招職業(yè)適應(yīng)性測試題庫完整
- 小學(xué)生國家文化安全教育
- 2024年常州工業(yè)職業(yè)技術(shù)學(xué)院單招職業(yè)技能測試題庫及答案解析
- AQ-T 3002-2021阻隔防爆橇裝式加油(氣)裝置技術(shù)要求
- 綠植租擺投標(biāo)方案
- 新聞編輯學(xué)PDF蔡雯第四版
- 行政處罰自由裁量權(quán)課件
- Unit-3-Reading-and-thinking課文詳解課件-高中英語人教版必修第二冊
- 肝病科進(jìn)修總結(jié)匯報(bào)
評(píng)論
0/150
提交評(píng)論