基于Unity3d的軍事模擬演練游戲開(kāi)發(fā)與實(shí)現(xiàn)_第1頁(yè)
基于Unity3d的軍事模擬演練游戲開(kāi)發(fā)與實(shí)現(xiàn)_第2頁(yè)
基于Unity3d的軍事模擬演練游戲開(kāi)發(fā)與實(shí)現(xiàn)_第3頁(yè)
基于Unity3d的軍事模擬演練游戲開(kāi)發(fā)與實(shí)現(xiàn)_第4頁(yè)
基于Unity3d的軍事模擬演練游戲開(kāi)發(fā)與實(shí)現(xiàn)_第5頁(yè)
已閱讀5頁(yè),還剩48頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

摘要隨互聯(lián)網(wǎng)信息時(shí)代改變?nèi)藗兩蠲芮邢嚓P(guān)的方方面面,而游戲和虛擬現(xiàn)實(shí)事業(yè)憑借著和互聯(lián)網(wǎng)的高契合性受到許多人對(duì)其的看好和關(guān)注。其中,射擊類(lèi)游戲可以給玩家們最為酣暢淋漓的快感,此類(lèi)游戲不僅能消除人們?cè)谏钪械膲毫Γ谟螒蛑懈苠憻挼椒磻?yīng)速度和心態(tài),同時(shí)還能提高對(duì)緊急情況的應(yīng)變能力,有著極廣的受眾群體。Unity3D游戲引擎憑借其較低的入門(mén)難度,開(kāi)發(fā)速度迅速的特點(diǎn)在近幾年來(lái)在市場(chǎng)中逐漸為大眾所知所用。本論文探究基于Unity3d的軍事模擬演練游戲開(kāi)發(fā)與實(shí)現(xiàn),跟隨的游戲的趨勢(shì),是一款兼容了第一人稱(chēng)和第三人稱(chēng)的射擊游戲,該游戲可以自由的切換人稱(chēng)來(lái)符合不同玩家的需求,同時(shí)添加了大逃殺元素,以添加大地圖以及搜集物資的模式使得該游戲充滿了各種隨機(jī)性要素,變成了一款玩法更加豐富的射擊游戲,需要玩家時(shí)刻保持警覺(jué),眾多的藏身地和遮擋物使得該游戲更具策略性,與槍法成為游戲的雙核心。而這種結(jié)合隨著2017年3月《絕地求生》的發(fā)布引發(fā)熱潮,眾多游戲廠商為了迎合市場(chǎng)開(kāi)發(fā)了一系列的大逃殺游戲,至今火熱,可見(jiàn)擁有著客觀的發(fā)展前景。本文主要描述該游戲結(jié)合引擎的開(kāi)發(fā)原理,游戲的設(shè)計(jì)與代碼實(shí)現(xiàn),同時(shí)對(duì)于游戲畫(huà)面的處理以及最終游戲功能測(cè)試,希望對(duì)后續(xù)開(kāi)發(fā)同類(lèi)型游戲的開(kāi)發(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í)代的變遷,人類(lèi)的娛樂(lè)活動(dòng)逐漸從實(shí)體轉(zhuǎn)移到了虛擬物體上。計(jì)算機(jī)網(wǎng)絡(luò)的普及,使人與人之間的聯(lián)系變得更為接近,即便是千里之外,亦能共享娛樂(lè)帶來(lái)的樂(lè)趣。毫無(wú)疑問(wèn)的說(shuō),虛擬娛樂(lè)方式的出世,極大的豐富了人們的娛樂(lè)方式,給人提供了釋放生活壓力的新方式,隨著人們對(duì)游戲的探究以及設(shè)備硬件的提高,人們?cè)絹?lái)越追求更加真實(shí)的感官,更深的浸入感,而能使玩家更能融入其中的3D游戲已經(jīng)為市場(chǎng)主流。而論最能釋放壓力的游戲方式,則是為緊張刺激的射擊類(lèi)游戲,由其衍生出來(lái)的大逃殺模式更是能讓人體會(huì)到腎上腺素飆升的快感。本次論文選擇的游戲引擎為時(shí)下流行的Unity3d引擎,Unity3D是讓開(kāi)發(fā)者玩家輕松創(chuàng)建三維模型可視化與渲染,現(xiàn)代化用戶(hù)交互界面程序或時(shí)下火熱的高性能3A游戲大作等多樣化互動(dòng)類(lèi)型的多平臺(tái)兼容的綜合型游戲開(kāi)發(fā)工具,最為顯著的特點(diǎn)是集成度高,開(kāi)發(fā)門(mén)檻低,很適合第一次接觸游戲制作的開(kāi)發(fā)者的一款引擎軟件。Unity3D引擎(簡(jiǎn)稱(chēng)U3D)在眾多游戲引擎中,算是比較年輕的一個(gè)引擎,由于近年來(lái)需求大量高科技人才,而U3D以他不高的入門(mén)門(mén)檻以及高便利性迅速的火了起來(lái),以至于各大公司對(duì)于能夠熟練使用U3D開(kāi)發(fā)軟件的人求賢若渴。作為一個(gè)主打游戲的引擎,在其他比如展廳項(xiàng)目、渲染效果圖等領(lǐng)域也開(kāi)拓了一大塊市場(chǎng)。而憑借U3D相比其他引擎較為短暫的入門(mén)周期,客觀理想的市場(chǎng)前景,使得如今各大高校也將U3D引擎的學(xué)習(xí)列入了一門(mén)專(zhuān)門(mén)課程,從側(cè)面也可以看出社會(huì)上能夠熟練的使用U3D制作游戲的人才可以得到薪資豐厚的工作,結(jié)合以U3D如今的發(fā)展趨勢(shì),毫無(wú)疑問(wèn)學(xué)習(xí)該引擎是一個(gè)不會(huì)令人后悔的選擇。本文正是想要通過(guò)自行制作游戲去理解游戲的整個(gè)流程,熟悉游戲制作上的相關(guān)技術(shù)。本次選擇的為時(shí)下大熱的“絕地求生”游戲,由于日常也有玩過(guò)這個(gè)游戲,對(duì)流程比較熟悉,所以具體闡述游戲的框架以及制作過(guò)程。而游戲本身的趣味性是毋庸置疑的,射擊類(lèi)游戲本身就有著極高的樂(lè)趣,每次命中敵人都有著一種獨(dú)特的快感,而且在現(xiàn)實(shí)生活中由于體力和體能的限制,并不是每個(gè)人都可以持槍射擊和奔跑,而在虛擬模擬演練中,可以盡情的奔跑和射擊,進(jìn)可持槍攻敵,退可伏地陰人??梢院痛蠹乙黄馉?zhēng)奪空投,游戲的多樣化帶了的娛樂(lè)性是十分豐富的。研究現(xiàn)狀自1981年,任天堂的拿手好作品《DonkeyKong》登場(chǎng)拉開(kāi)帷幕以來(lái),至今游戲行業(yè)的發(fā)展已歷經(jīng)幾輪巨變。遙想當(dāng)年,游戲界尚處于萌芽階段,主人公馬里奧第一次出現(xiàn)在大眾視野中,何人曾猜到這個(gè)普通的水管工能擔(dān)任后來(lái)任天堂的首席形象代表,那時(shí)正是街機(jī)游戲百花齊放的12年,游戲行業(yè)的開(kāi)始了蓬勃發(fā)展,其中日本更是為此行業(yè)的霸主。3D游戲的起源來(lái)自于90年代的美國(guó),自3D游戲引擎的問(wèn)世后瞬間擴(kuò)展全球。從那時(shí)候開(kāi)始,游戲產(chǎn)業(yè)的豐厚收入甚至超過(guò)了傳統(tǒng)工業(yè),巨大的市場(chǎng)使世界各大經(jīng)濟(jì)強(qiáng)國(guó)重新開(kāi)始審視游戲行業(yè),游戲產(chǎn)業(yè)的地位也逐漸水漲船高,。中韓國(guó)政府對(duì)于游戲的大力支持使得韓國(guó)能夠后來(lái)居上,如今的游戲發(fā)展規(guī)模已經(jīng)和當(dāng)初的霸主日本平分秋色,而韓國(guó)發(fā)展的最為優(yōu)秀的網(wǎng)絡(luò)游戲方面更是奪得了亞洲的王冠,而如今韓國(guó)的經(jīng)濟(jì)支柱之一已經(jīng)妥妥的由游戲產(chǎn)業(yè)帶來(lái)的效益支撐。結(jié)合我國(guó)之前的發(fā)展需求以及傳統(tǒng)觀點(diǎn)的影響,游戲行業(yè)在我國(guó)發(fā)展處于起步晚、經(jīng)驗(yàn)不足的情況。并且由于經(jīng)濟(jì)實(shí)力以及開(kāi)發(fā)周期等原因,除了大型公司,國(guó)內(nèi)多數(shù)公司在權(quán)衡利弊之后,還是更加穩(wěn)妥的選擇了國(guó)外更為成熟的游戲引擎工具,眾多引擎之中,Unity3D和虛幻在我國(guó)最為青睞,兩大巨頭平分秋色。但今年來(lái)我國(guó)游戲的收入也有著顯著的提升,伽馬數(shù)據(jù)REF_Ref25256\w\h[1]REF_Ref19843\w\h[12]發(fā)布《2019中國(guó)游戲產(chǎn)業(yè)年度報(bào)告》顯示,2019年我國(guó)游戲市場(chǎng)實(shí)際銷(xiāo)售收入2330.2億元,同比增長(zhǎng)8.7%,用戶(hù)規(guī)模、自主研發(fā)、海外市場(chǎng)等主要指標(biāo)均明顯好于去年同期。目REF_Ref19758\w\h[13]前中國(guó)自主研發(fā)的移動(dòng)游戲在美、日、韓、英、德等國(guó)家的流水同比增長(zhǎng)率均高于該國(guó)移動(dòng)游戲市場(chǎng)的增速,表明國(guó)產(chǎn)移動(dòng)游戲在海外市場(chǎng)已經(jīng)建立一定的創(chuàng)新優(yōu)勢(shì)。將游戲與文化結(jié)合是打造精品的重要方向。2019年上半年,游戲廠商游族網(wǎng)絡(luò)海外地區(qū)營(yíng)業(yè)收入達(dá)到10.09億元,占總營(yíng)業(yè)收入的58.36%。得到海外市場(chǎng)認(rèn)可,很重要一點(diǎn)就是文化融入。可以看出隨著移動(dòng)硬件設(shè)備的提升,移動(dòng)游戲也開(kāi)始了驚人的增長(zhǎng),同時(shí)移動(dòng)電競(jì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)行,通過(guò)網(wǎng)絡(luò)傳送給用戶(hù),破解游戲?qū)Ω叨穗娔X配置等的依賴(lài),成為當(dāng)前創(chuàng)新的主要方向之一。一旦普遍,移動(dòng)端市場(chǎng)將會(huì)進(jìn)一步擴(kuò)大,而Unity3D的跨平臺(tái)特性將會(huì)具備巨大優(yōu)勢(shì),熟練使用該引擎有著不可忽視的戰(zhàn)略意義。論文組織結(jié)構(gòu)?論文從構(gòu)思設(shè)計(jì),參考著相關(guān)的博客以及技術(shù)書(shū)籍,整合了前人的經(jīng)驗(yàn),完成了一個(gè)模擬軍事演練的槍?xiě)?zhàn)游戲制作。下文將通過(guò)游戲的制作展示U3D的相關(guān)組件和操作,同時(shí)也分享一下有關(guān)于游戲的制作流程和個(gè)人制作該游戲的心得,其中著重分享游戲的功能設(shè)計(jì)及其代碼的編寫(xiě)實(shí)現(xiàn)。現(xiàn)將論文根據(jù)游戲制作過(guò)程分解成主要的六大章,各章節(jié)的如下安排:第一部分:緒論,主要闡述了該畢業(yè)設(shè)計(jì)制作的背景、國(guó)內(nèi)外對(duì)相關(guān)課題的研究現(xiàn)狀以及本設(shè)計(jì)的大概介紹;?

第二部分:對(duì)U3D的部分功能進(jìn)行介紹,并且推薦以下本游戲制作過(guò)程中使用到的各類(lèi)開(kāi)發(fā)工具以及引用的插件。第三部分:講述游戲的場(chǎng)景以及用戶(hù)交互界面的設(shè)計(jì)使用到的組件及實(shí)現(xiàn)。 第四部分:詳細(xì)介紹游戲的各個(gè)模塊的制作,清晰明確游戲內(nèi)部關(guān)系,采用由下到上的順序?qū)訉硬鹞霾襟E直觀介紹下整個(gè)游戲流程以及游戲框架的設(shè)計(jì)和搭建,并且展示游戲中各模塊比較核心的腳本源代碼,采用由主及枝詳細(xì)解析各步驟。

第五部分:闡述一些屏幕后處理以及著色器的實(shí)現(xiàn)。第六部分:展示一下游戲運(yùn)行數(shù)據(jù)以及測(cè)試結(jié)果。第七部分:制作該游戲的心得,針對(duì)游戲中一些不足和缺陷進(jìn)行總結(jié),以及如何改良。?

Unity游戲引擎及插件軟件介紹Unity3D游戲引擎Unity3D引擎介紹Unity3D引擎(以下簡(jiǎn)稱(chēng)U3D)是UnityTechnologies研發(fā)的讓玩家輕松創(chuàng)建豐富的互動(dòng)內(nèi)容軟件的多平臺(tái)的綜合型游戲開(kāi)發(fā)工具,完美的跨平臺(tái)系統(tǒng)大大提高了不同平臺(tái)移植的工作效率。同時(shí)U3D還具備高度集成的系統(tǒng),以及優(yōu)秀的用戶(hù)交互操作界面,使得用戶(hù)能夠輕易入手該軟件創(chuàng)建自己的工程。其中五個(gè)視圖框架Project(存放資源文件)、Hierarchy(放置游戲?qū)ο螅cene(預(yù)覽編輯界面)、Game(游戲運(yùn)行結(jié)果)、inspector(查看對(duì)象的信息)合理放置并且多利用編輯器的快捷鍵可以使工作效率得到顯著的提高。以上所說(shuō)的都是U3D比較表面的東西,現(xiàn)如今U3D在不斷的優(yōu)化,引入了燈光、地形、動(dòng)畫(huà)、渲染、粒子系統(tǒng)、可編程shader、物理系統(tǒng)等等。而引擎支持的語(yǔ)言為C#、javascript、boo三種腳本語(yǔ)言,其中C#由于優(yōu)秀的性能使得官方對(duì)其優(yōu)化力度也較高,所以大多數(shù)使用者選擇了C#。Unity3D常用函數(shù)由于U3D的高度集成性,在實(shí)現(xiàn)功能時(shí),常常可以借用U3D提供的函數(shù)來(lái)完成,可以通過(guò)繼承和引用命名空間的方式來(lái)獲取函數(shù),同時(shí)也可以通過(guò)繼承重載函數(shù),我們可以通過(guò)進(jìn)入函數(shù)內(nèi)部結(jié)構(gòu)查看內(nèi)置函數(shù)的說(shuō)明。而U3D不像使用Vs編寫(xiě)程序一樣,需要從Main函數(shù)入口進(jìn)入運(yùn)行,只需要引用UnityEngine命名空間并繼承MonoBehavior腳本并掛載到場(chǎng)景物體上運(yùn)行時(shí)內(nèi)部就會(huì)不斷迭代以下的生命函數(shù)REF_Ref25684\w[4]:Awake():物體初始化時(shí)調(diào)用,無(wú)論是否被激活。Start():晚于Awake()執(zhí)行,同時(shí)需要激活物體。OnEnable():每次激活該物體都會(huì)執(zhí)行一次,適用于每次打開(kāi)的物體的初始化。Update();每幀都會(huì)調(diào)用一次,幀率是不穩(wěn)定的,對(duì)標(biāo)的為FixedUpdate(),區(qū)別在于FixedUpdate是固定幀,同時(shí)可以通過(guò)Application.targetFrameRate對(duì)游戲幀數(shù)進(jìn)行鎖定。LateUpdate():在Update(),后執(zhí)行,用于比如相機(jī)渲染等需要最后刷新的函數(shù)執(zhí)行。DisEnable():每次關(guān)閉物體使用一次,通過(guò)使用gameobject.Setive來(lái)控制物體的開(kāi)關(guān)觸發(fā)。另外還還有些常用的函數(shù):OnTriggerEnter():需要碰撞體組件并且開(kāi)啟Trigger模式,當(dāng)有剛體(Rigidbody)組件的物體進(jìn)入該物體使則會(huì)一直調(diào)用里面的函數(shù)。OnCollisionEnter():和OnTriggerEnter():不同,兩個(gè)都需要碰撞體和剛體,碰撞則觸發(fā)一次OnCollisionEnter2D():同OnCollisionEnter(),只是為二維對(duì)象。OnTriggerEnter()、OnTriggerStay()、OnTriggerExit()為一組,分別代表進(jìn)入、保持進(jìn)入、離開(kāi),只有Stay會(huì)一直觸發(fā),其他的均自觸發(fā)一次。每一個(gè)在引擎內(nèi)新建的腳本范本都會(huì)繼承和引用基類(lèi),在制作一些類(lèi)似節(jié)點(diǎn)的腳本,或者結(jié)構(gòu)體等不需要再周期內(nèi)調(diào)用的函數(shù),可以自行去掉節(jié)省資源,后期可通過(guò)GC內(nèi)存管理清理不必要的內(nèi)存。2.1.3GUI(Unity3D自帶用戶(hù)圖形界面)本次游戲的制作使用引擎自帶的UGUI進(jìn)行UI界面的開(kāi)發(fā),GUI是圖形用戶(hù)界面的簡(jiǎn)稱(chēng),又叫圖形用戶(hù)接口。由于UI界面的存在,用戶(hù)不需要太高的專(zhuān)業(yè)性,做到了將技術(shù)性隱藏起來(lái),同時(shí)增加了美觀性。通過(guò)使用UGUI可以簡(jiǎn)單快捷的添加封裝好的各類(lèi)界面元素,在創(chuàng)建完畢時(shí)候,引擎會(huì)實(shí)例化功能定義,而腳本中只需要獲取并且引用即可修改其中的資源信息,相對(duì)于遠(yuǎn)古版本的OnGUI(U3D自帶的腳本實(shí)現(xiàn)UI界面),顯著的提高了編輯速度以及客觀性,同時(shí)后期由于控件封裝的功能,可以使后期的修改位置角度或圖片等元素十分快捷,后期跨平臺(tái)或改變分辨率后對(duì)于空間的調(diào)整也不至于那么麻煩,極大的減少了開(kāi)發(fā)時(shí)間以及設(shè)計(jì)的代碼量。2.1.4物理引擎及其他系統(tǒng)物理引擎是通過(guò)剛性物體賦予真實(shí)的物理屬性的方式來(lái)計(jì)算運(yùn)動(dòng)、旋轉(zhuǎn)和碰撞反映。如今的游戲以3d游戲?yàn)橹髁髭厔?shì),而物理系統(tǒng)也成為了游戲的不可或缺要素,可以說(shuō)一個(gè)開(kāi)發(fā)者能將物理引擎完美融入到游戲性,那么這個(gè)游戲必將成為游戲中的佼佼者。雖說(shuō)物理系統(tǒng)可以通過(guò)自己編程來(lái)實(shí)現(xiàn),而對(duì)于初窺門(mén)徑的開(kāi)發(fā)者來(lái)說(shuō),無(wú)疑是舉步為艱。而U3D為開(kāi)發(fā)者提供了一系列物理組件,讓開(kāi)發(fā)者不需要深入了解原理即可初步使用組件構(gòu)架出物理法則世界。無(wú)獨(dú)有偶,單單有物理系統(tǒng)是無(wú)法讓玩家沉浸其中,U3D提供了譬如地形、粒子、著色器、音效、動(dòng)畫(huà)機(jī)、材質(zhì)球、音效、貼圖、智能導(dǎo)航等等組件,使得初學(xué)乍練的開(kāi)發(fā)者能滿懷熱情去探索游戲世界。2.1.5DoTween插件DOTween是一款針對(duì)于Unity開(kāi)發(fā)的快速,高效兼顧類(lèi)型安全的面向?qū)ο蟮拿赓M(fèi)動(dòng)畫(huà)引擎,針對(duì)C#用戶(hù)進(jìn)行了開(kāi)源優(yōu)化,具有大量提高效率的功能。因?yàn)橐磺卸急痪彺娌⑶抑赜?,避免了無(wú)用的GC分配,實(shí)現(xiàn)同時(shí)兼顧速度與效率。當(dāng)前開(kāi)發(fā)團(tuán)隊(duì)更新了更為專(zhuān)業(yè)和高性能的進(jìn)階收費(fèi)版本,但本次游戲我們僅需在Unity商店下載免費(fèi)版本足以使用。通過(guò)本插件可以方便快捷的制作補(bǔ)間動(dòng)畫(huà)。不論是顏色、位置或者大小,在引入插件命名空間后直接調(diào)用物體的tranform組件即可輕易的調(diào)用函數(shù)實(shí)現(xiàn)動(dòng)畫(huà)。由于其應(yīng)用廣、邏輯易用、自由度高等特點(diǎn),已經(jīng)成為了每個(gè)使用Unity的新手最為熱門(mén)的入門(mén)插件之一。2.2C#開(kāi)發(fā)語(yǔ)言C#是微軟公司發(fā)布的一種面向?qū)ο蟮?、運(yùn)行于.NET

Framework和.NET

Core(完全開(kāi)源,跨平臺(tái))之上的高級(jí)程序設(shè)計(jì)語(yǔ)言。C#在不損失C/C++原有強(qiáng)大的功能和編寫(xiě)的豐富類(lèi)庫(kù)的前提下,能夠讓使得C++程序員可以高效的開(kāi)發(fā)程序。C#是C的衍生,因而與C/C++具有著極大相似性,意味著了解類(lèi)似語(yǔ)言的開(kāi)發(fā)者可以快速的轉(zhuǎn)向C#。C#并不同于LUA、PYTHON具備跨平臺(tái)的特性,所以Unity殷勤通過(guò)Mono虛擬機(jī)將代碼實(shí)時(shí)編譯或者預(yù)先編譯到原生代碼實(shí)現(xiàn)移植到非Windows平臺(tái)的。選擇該語(yǔ)言,是因?yàn)镃#在網(wǎng)絡(luò)開(kāi)發(fā)方面成績(jī)很優(yōu)秀、同時(shí)相對(duì)于動(dòng)態(tài)語(yǔ)言js更加穩(wěn)定,具備優(yōu)秀的類(lèi)庫(kù),同時(shí)U3D開(kāi)發(fā)團(tuán)隊(duì)也更傾向?qū)τ贑#進(jìn)行優(yōu)化。2.3VisualStudioCode軟件Visual

Studio

Code軟件是微軟公司于2015年4月30日在Build開(kāi)發(fā)者大會(huì)上正式推出的一款輕量級(jí)的跨平臺(tái)源代碼編輯器。使用該軟件進(jìn)行代碼的編寫(xiě)可以使系統(tǒng)資源占用大幅度減少,同時(shí)最為人稱(chēng)道的是他的極其強(qiáng)大的拓展性,,使得每個(gè)用戶(hù)都能夠找到自己想要的大部分功能。我最終選擇該軟件進(jìn)行編程的原因是因?yàn)槠鋬?nèi)嵌的小地圖,信息預(yù)覽和使用詳情,同時(shí)支持全局替換,這對(duì)于后期的優(yōu)化以及調(diào)試有著巨大的便利性。美術(shù)資源設(shè)計(jì)3.1場(chǎng)景設(shè)計(jì)3.1.1地形繪制正如前文提到的Unity自帶了地形(Terrian)系統(tǒng),本次游戲地形的制作就是通過(guò)該系統(tǒng)創(chuàng)建而成。該組件該組件類(lèi)似于Maya中使用置換貼圖實(shí)現(xiàn)變形高段數(shù)的多邊形平面,原理是通過(guò)中等多邊形密度的多邊形平面,再指定一張灰階圖作為高插圖,根據(jù)mesh各頂點(diǎn)對(duì)應(yīng)的灰度數(shù)值改變Y軸的高度形成高低起伏的地形。通過(guò)Create->3DObject->Terrain在Hierarchy面板創(chuàng)建對(duì)象(如圖4.1-1),該組件的Terrian屬性欄最上排有七個(gè)主要按鈕,除了最后一個(gè)設(shè)置按鈕,其他的都是以筆刷的形式繪制地形,簡(jiǎn)單介紹一下功能REF_Ref26938\w\h[5]。圖3-1創(chuàng)建地形Raise

Lower

Terrain、Paint

Height、Smooth

Height

這三個(gè)選項(xiàng)

點(diǎn)擊后都會(huì)出現(xiàn)筆刷面板,通過(guò)自定義筆刷大?。˙rushSize)和明度(Opacity)和筆刷類(lèi)型可自定義繪制的地形,通過(guò)鼠標(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ù)順序起到的作用分別為在地形表面繪制貼圖、添加大型物體(通常用來(lái)做樹(shù))、添加細(xì)節(jié)物體(如草叢、花),自定義添加物體需要需要在Textures/Trees/details欄中點(diǎn)擊編輯按鈕,再選擇對(duì)應(yīng)的資源即可直接在地圖中刷出物體,十分便捷,同時(shí)可以設(shè)置透明度改變刷出物的密度(如圖3-2)。

圖3-2添加編輯物體3.1.2添加風(fēng)塵效果完成了地形的繪制后,我們?cè)趫?chǎng)景中添加風(fēng)塵的效果,提高游戲的沉浸度和浸入感。首先制作一個(gè)風(fēng)塵粒子效果15,Unity中同樣集成了粒子系統(tǒng),在Hierarchy面板創(chuàng)建一個(gè)ParticelSystem,打開(kāi)Inspector欄可以看到許多的選項(xiàng),簡(jiǎn)單介紹一下我使用到的屬性REF_Ref26990\w\h[6]。(如圖3-3)圖3-3粒子效果基本屬性:其中包括粒子的動(dòng)畫(huà)時(shí)間、是否循環(huán)、發(fā)射速度和角度,顏色和最大粒子數(shù)等屬性,由于風(fēng)塵的凌亂我將發(fā)射角度和速度以及顏色各屬性設(shè)置在了一個(gè)區(qū)間內(nèi)隨機(jī)。Emission:控制發(fā)送速率,會(huì)影響粒子數(shù)量。Shape:控制發(fā)射場(chǎng)的形狀,這里設(shè)置為Box。Coloroverlifetime:控制生命周期內(nèi)顏色變化,可多個(gè)顏色混合或取隨機(jī)值。Rotationoverlifetime:控制生命周期內(nèi)的角度變化,可多個(gè)角度混合或取隨機(jī)值。Renderer:可以改變粒子的渲染材質(zhì)或者切換網(wǎng)格體等一系列渲染參數(shù)。為了場(chǎng)景中的物體受到風(fēng)的影響,我們?cè)诘匦蜗绿砑语L(fēng)場(chǎng)(WindZone),配置了風(fēng)場(chǎng)效果后,場(chǎng)景內(nèi)的樹(shù)會(huì)根據(jù)風(fēng)場(chǎng)的方向和速度搖曳。(如圖3-4)圖3-4添加風(fēng)場(chǎng)后的場(chǎng)景效果3.1.3添加建筑物地形制作和風(fēng)塵效果實(shí)現(xiàn)后,我們將房子模型預(yù)設(shè)體放置于場(chǎng)景中,為不可通過(guò)的物體(如墻、柵欄)添加對(duì)應(yīng)的碰撞體(不規(guī)則的模型可用MeshCollider啟動(dòng)convex屬性,網(wǎng)格便會(huì)完美貼合于模型上),同時(shí)為所有門(mén)添加之前便寫(xiě)好的交互腳本。在場(chǎng)景中選擇合適的位置添加敵人預(yù)設(shè)范圍和玩家出生點(diǎn),最終為所有的房子添加生存資源自動(dòng)生成器(創(chuàng)建一個(gè)Cube關(guān)掉渲染效果和碰撞器同時(shí)添加ItemSpawner腳本,如圖3-5)。圖3-5配置完畢的場(chǎng)景3.1.4添加水面動(dòng)效島嶼四周的水面以及島中的一些水池如果只是用單純的面片的話會(huì)顯得十分的死板,而讓水面有動(dòng)態(tài)的效果有兩種做法,一是通過(guò)修改面片的法線起到高低起伏的效果,二是通過(guò)著色器修改。而第二種方法由于節(jié)省大量的資源被大眾所提倡使用,這次我也通過(guò)這種方式實(shí)現(xiàn)水面的動(dòng)效。首先,我們要先明白著色器的渲染流水線有兩個(gè)比較重要的階段為頂點(diǎn)處理和像素處理,而并不改變定點(diǎn)的信息,所以主要針對(duì)的是像素程序的編寫(xiě)。主要的思路就是主貼圖的uv坐標(biāo)隨時(shí)間改變,而在著色器中實(shí)現(xiàn)隨機(jī)的效果一般通過(guò)導(dǎo)入一張?jiān)朦c(diǎn)圖,根據(jù)獲取噪點(diǎn)圖的差值信息和原圖進(jìn)行疊加,最終輸出的結(jié)果就是為隨機(jī)波動(dòng)的圖像動(dòng)畫(huà)了,核心代碼和效果圖如下。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(用戶(hù)交互界面)設(shè)計(jì)UI面板分為游戲面板:背包面板、小地圖大圖面板、玩家游戲信息面板(指針、擊殺信息、準(zhǔn)心瞄準(zhǔn)鏡、血量能量條、子彈情況、倒計(jì)時(shí)、存活數(shù)量、公告信息)以及游戲系統(tǒng)面板:勝負(fù)界面、游戲菜單界面。(如圖3-6)圖3-6游戲UI的層級(jí)分布所有需要開(kāi)關(guān)的UI面板都可以通過(guò)掛載PanelInstance這個(gè)單例腳本,同時(shí)在該腳本中引用了Dotween插件,在OnEnbale中使用了插值動(dòng)畫(huà),使每次打開(kāi)面板時(shí)能夠?qū)崿F(xiàn)變大逐漸呈現(xiàn)的插值動(dòng)畫(huà)效果,再在游戲初始化時(shí)獲取所有的交互面板到面板管理器中PlayerHUDCanvas(PanelsManager)。//利用DG實(shí)現(xiàn)過(guò)場(chǎng)動(dòng)畫(huà)效果

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ì)了多種情形下打開(kāi)和關(guān)閉腳本的方式,但總歸都是通過(guò)數(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ù)名字打開(kāi)相應(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ì)本次開(kāi)發(fā)的游戲,玩家通過(guò)鼠標(biāo)和鍵盤(pán)進(jìn)行角色的操控。在游玩的過(guò)程中,玩家可以進(jìn)行人稱(chēng)視角的切換、通場(chǎng)景的物體進(jìn)行交互、行走跳躍、同時(shí)還可以改變進(jìn)行的狀態(tài),可以走跑蹲趴,令玩擁有豐富的進(jìn)攻方式和隱蔽自己的方式。在游戲的一開(kāi)始玩家會(huì)在出生島等待,繼而會(huì)到飛機(jī)上跳傘到達(dá)軍事演練地點(diǎn),通過(guò)搜集散落在場(chǎng)景中的軍事物資,通過(guò)靈活多變的方式淘汰對(duì)手,在過(guò)程中,會(huì)逐漸縮減安全范圍,當(dāng)最后一個(gè)人存活時(shí),游戲方能結(jié)束。每當(dāng)一定的時(shí)間間隔,都會(huì)生成具有肥沃物資的空投予于玩家拾取REF_Ref27111\w[3]REF_Ref27118\w[2]??偨Y(jié)規(guī)則后可以將游戲的主要功能分為三部分:實(shí)現(xiàn)玩家對(duì)游戲角色的控制、在玩家系統(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)對(duì)應(yīng)輸入的功能,這種歸納到一個(gè)腳本控制的做法對(duì)于后期的調(diào)試有著極大的幫助。如下圖所示,數(shù)字1-5代表著對(duì)應(yīng)類(lèi)型武器的切換,而WSAD鍵用以控制玩家角色的移動(dòng),Tab鍵控制背包的開(kāi)關(guān),C鍵用于改變玩家的行走姿態(tài),V鍵用以控制玩家視野的改變,M鍵控制大地圖的打開(kāi),而F鍵控制的則是與場(chǎng)景中各種物體的交互,譬如打開(kāi)門(mén)、拾取物體、離開(kāi)飛機(jī)等事件。而鼠標(biāo)左鍵控制玩家進(jìn)行攻擊事件,右鍵打開(kāi)瞄準(zhǔn)功能(需武器本身?yè)碛写斯δ芙涌冢瑫r(shí)鼠標(biāo)的移動(dòng)控制視角的旋轉(zhuǎn)。代碼中可以通過(guò)Input.Get..系列腳本可以監(jiān)聽(tīng)相應(yīng)的按鍵事件,GetAxis()以及GetButton()函數(shù)對(duì)應(yīng)的鍵值可以在編輯器Edit->ProjectSetting->Input中修改相應(yīng)的監(jiān)聽(tīng)鍵值,而GetKeyDown(KeyCode)可以直接監(jiān)聽(tīng)傳入的鍵是否被按下。4.2.2玩家的生成無(wú)論是玩家、敵人亦或是隨機(jī)刷新的軍事物資生成的原理都是相同的,獲取已經(jīng)配置好的預(yù)設(shè)體,然后使用Instantiate()傳入需要生成的物體、位置以及角度即可生成。而為了保持相對(duì)的隨機(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()并編寫(xiě)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)))

);}

//檢測(cè)腳下的地面高度

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)我們?cè)谠O(shè)置區(qū)域大小的時(shí)候正是修改的此值,因此這里localScale實(shí)際上就等于一個(gè)長(zhǎng)度的獲取。同時(shí)為了物體能正確的顯示在地面(由于山體坡度的不統(tǒng)一需要實(shí)時(shí)獲?。枰@取一個(gè)正確的高度點(diǎn),將獲得的隨機(jī)點(diǎn)向下發(fā)射一次射線,當(dāng)檢測(cè)到碰撞信息再加上一個(gè)向上的單位向量Vector3.Up即可保證該高度恰巧處于地面之上。首先需要定義一個(gè)RaycastHit射線,然后調(diào)用Physics.Raycast()初入發(fā)射起點(diǎn)和方向以及長(zhǎng)度,即可將射線碰撞的信息存入Hit中,而Hit.Point就是射線檢測(cè)到的地面坐標(biāo)點(diǎn)。此時(shí)只需要調(diào)用Instantiate()傳入物體、位置。角度即可生成相應(yīng)的物體。Instantiate(gameObject,SpawnPoint(PlayerSpawner.tranform,position),Quaternion.identity)

;

4.2.3動(dòng)畫(huà)系統(tǒng)在第三人稱(chēng)游戲中需要十分多的動(dòng)畫(huà)過(guò)度,在Unity中過(guò)度動(dòng)畫(huà)需要先對(duì)動(dòng)畫(huà)機(jī)進(jìn)行配置,如圖,首先將所有的人物動(dòng)畫(huà)放置到動(dòng)畫(huà)機(jī)中,并按照相應(yīng)的動(dòng)畫(huà)轉(zhuǎn)化條件將動(dòng)畫(huà)連接起來(lái)并設(shè)置相應(yīng)的變量值,然后在Conditions設(shè)置觸發(fā)動(dòng)畫(huà)間的觸發(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)畫(huà)機(jī)系統(tǒng)配置接下來(lái)只需要在代碼中獲取動(dòng)畫(huà)機(jī)Animator,并且相應(yīng)的變量類(lèi)型調(diào)用設(shè)置函數(shù),傳入對(duì)應(yīng)的變量名和數(shù)值即可對(duì)動(dòng)畫(huà)機(jī)的狀態(tài)進(jìn)行改變。如上述代碼則是確認(rèn)存在動(dòng)畫(huà)機(jī)的情況下,設(shè)置Trigger類(lèi)型的變量Shoot為觸發(fā)狀態(tài),設(shè)置Shoot_Typed的int變量為對(duì)應(yīng)的狀態(tài)。4.2.4場(chǎng)景交互的實(shí)現(xiàn)游戲中需要許多需要交互的東西,如圖所示,當(dāng)玩家屏幕對(duì)準(zhǔn)物體時(shí),會(huì)顯示物體的相關(guān)信息,其他處于可交互狀態(tài)的情況下也會(huì)出現(xiàn)可交互的示意文字。這意味著在游戲中會(huì)按照一定頻率對(duì)屏幕中心物體進(jìn)行檢測(cè),當(dāng)為可交互的物體時(shí)而對(duì)玩家進(jìn)行反饋,而按下交互鍵使則執(zhí)行對(duì)應(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()中不斷刷新的射線一旦檢測(cè)到有可交互的物體,就會(huì)通過(guò)獲取的碰撞體發(fā)送調(diào)用GetInfo()函數(shù)的信息,這里發(fā)送信息的方法為SendMessage(),首先需要傳入調(diào)用的函數(shù),后面為設(shè)置接受者是否需要為監(jiān)聽(tīng)狀態(tài),而SendMessageOptions.DontRequireReceiver表示不需要為接受者狀態(tài)。(如圖4-5)public

override

void

GetInfo()

{

YZW.Hud.ShowInfo("按下“F”開(kāi)門(mén)",

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場(chǎng)景交互以門(mén)的反饋信息為例,如上圖4-5所示,當(dāng)可交互物體被檢測(cè)到時(shí)反饋本身的信息到玩家的交互界面控制器HudManager中,而HudManager中的ShowInfo()會(huì)將場(chǎng)景中的提示文本的游戲?qū)ο蟠蜷_(kāi),在通過(guò)GetWorldSpaceUIposition()將物體的世界坐標(biāo)轉(zhuǎn)化為屏幕坐標(biāo)以確保文本在物體中心位置,最后在替換文本。同理,當(dāng)玩家按下交互鍵時(shí)可以同樣發(fā)射一條射線確認(rèn)當(dāng)前的物體可交互,并且請(qǐng)求調(diào)用該物體腳本中的交互函數(shù),則可以進(jìn)行玩家角色和場(chǎng)景的交互。4.2.5背包系統(tǒng)人物需要和場(chǎng)景內(nèi)的物體交互,主要行為是將場(chǎng)景內(nèi)的演習(xí)資源放入背包中,將物品丟棄,武器裝彈消耗背包內(nèi)物體。由于只有當(dāng)玩家距離交互物體到一定距離并且對(duì)準(zhǔn)物體才能進(jìn)行交互,所以需要一直檢測(cè)玩家是否檢測(cè)到了交互物體,通過(guò)發(fā)射射線對(duì)當(dāng)前視角中心的物體進(jìn)行檢測(cè),當(dāng)玩家有物體時(shí),將物體信息傳入總控制器中的ui部分并且顯示出來(lái)提示玩家可以進(jìn)行交互。當(dāng)玩家按下交互鍵時(shí),則發(fā)送信息,如果是物體的話則將物體存入背包中。當(dāng)存入物品過(guò)多超過(guò)了背包的容量想要丟棄部分不需要的物資時(shí),只需點(diǎn)擊UI面板中背包面板中想要丟棄的物品即可丟出。當(dāng)武器進(jìn)行換彈時(shí),會(huì)讀取當(dāng)前槍支的最大容量和當(dāng)前容量計(jì)算出需要消耗的子彈數(shù)量進(jìn)行填充。(如圖4-6)圖4-6背包系統(tǒng)在游戲中搜集物資需要對(duì)物體進(jìn)行存儲(chǔ)、丟棄以及使用。而物品的存儲(chǔ)需要將物品以及數(shù)量一一對(duì)標(biāo),同時(shí)由于物體的特性不同,需要定義類(lèi)型來(lái)區(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);

}

由于物品的特性不同,通過(guò)枚舉將所有的類(lèi)型列舉出來(lái)。每個(gè)物體具備多個(gè)特性,所以這里將物體的各項(xiàng)屬性編寫(xiě)成一個(gè)ItemCollector類(lèi),方便我們將其存入列表中。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);

}

在對(duì)物體進(jìn)行存儲(chǔ)時(shí),通過(guò)For循環(huán)確認(rèn)列表是否以及有相同物體,如果列表中已經(jīng)存在該物體,則直接將加入的物體數(shù)量疊加到列表中物體,而如若沒(méi)有該物體,則添加該物體到列表中。丟棄物品時(shí)則相反,由于丟棄的數(shù)量不一定為全部,所以需要對(duì)物體的數(shù)量進(jìn)行判斷,如果丟棄后數(shù)量為0時(shí)則移除該物體。4.2.6音效控制在Unity中使用音頻需要用到AudioSource和AudioClip兩個(gè)組件,AudioSource類(lèi)似于一個(gè)播放器,而AudioClip則是用來(lái)掛載音源。通過(guò)調(diào)用AudioSource的PlayOneShot()方法即可播放音源,與Play()方法不同,playOneShot就是為了解決播放多種和多次音效的問(wèn)度題而生的(個(gè)人觀點(diǎn)),這函數(shù)不管你目前有沒(méi)有正在播放音效,它都會(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;

}

通過(guò)獲取當(dāng)前角色的移動(dòng)速度來(lái)控制音頻的播放速率,速度越快,則音頻結(jié)束的速度越快,為了腳步看起來(lái)自然,這里我導(dǎo)入了三個(gè)音頻隨機(jī)播放,如下圖4-7所示。圖4-7音頻控制4.2.7人物的基本移動(dòng)移動(dòng)和跳躍可以說(shuō)是3d游戲中最基礎(chǔ)的移動(dòng),在Unity中使用物理系統(tǒng)進(jìn)行最基礎(chǔ)的移動(dòng)方式主要通過(guò)給予玩家物體剛體組件,通過(guò)施加力來(lái)控制玩家的移動(dòng)和跳躍,而前文我們提到的加速則是通過(guò)增大施加力的數(shù)值達(dá)到更快的速度。角色控制器是官方基于剛體設(shè)計(jì)的專(zhuān)門(mén)用于角色的基本控制的組件,如圖4-8所示,具有角色移動(dòng)主要的幾項(xiàng)屬性,本次我們?cè)诖私M件的基礎(chǔ)上編寫(xiě)玩家的移動(dòng)和跳躍時(shí)間。圖4-8角色控制器組件角色控制器中有編寫(xiě)好的移動(dòng)函數(shù),只需要傳入移動(dòng)的方向和數(shù)值即可進(jìn)行移動(dòng)。跳躍的本質(zhì)是向上人體對(duì)地面施加一個(gè)力,反作用力將人體推向天空,而在地心引力的作用下人體速度逐漸衰減然后下降到地面,因此我們需要?jiǎng)?chuàng)建一個(gè)模擬的重力場(chǎng),并給予物體一個(gè)向上的加速度,并實(shí)時(shí)計(jì)算在重力的情況下速度的衰減變化,通過(guò)isGrounded檢測(cè)是否回到地面來(lái)控制跳躍狀態(tài)的開(kā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ì)開(kāi)始沿著子彈的正前方不斷的刷新自身的位置。public

void

Update(){

this.transform.position

+=

this.transform.forward

*

Speed

*

Time.deltaTime;

}

當(dāng)子彈命中敵人或地面以及到達(dá)銷(xiāo)毀時(shí)間時(shí)就會(huì)刪除該物體,這里直接用Destory函數(shù)銷(xiāo)毀物體,第二個(gè)參數(shù)代表延遲的時(shí)間。public

void

Start(){

GameObject.Destroy(this.gameObject,

lifeTime);

}

當(dāng)玩家進(jìn)行射擊時(shí),為了還原槍械后坐力的效果,這里采用了Dotween插件中的Punching函數(shù)對(duì)相機(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)畫(huà)時(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ù)對(duì)自身的血量進(jìn)行修改,并且反饋到屏幕。主要的流程和前文一樣,都是通過(guò)調(diào)用交互界面管理器進(jìn)行反饋。(如圖4-9)圖4-9受擊效果4.3敵人AIAI敵人需要模擬真實(shí)玩家的效果,由于敵人和玩家之間的代碼可以大量的復(fù)用,所以只需要對(duì)敵人的狀態(tài)能夠起到根據(jù)情況能自主的進(jìn)行轉(zhuǎn)換即可,根據(jù)功能的需求,機(jī)器人具備的狀態(tài)有,在原地站立、尋找敵人的狀態(tài)、移動(dòng)到安全區(qū)的狀態(tài)。促使敵人行為狀態(tài)的改變?cè)赜袃?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īng)顟B(tài)的時(shí)間到了,那么敵人就會(huì)轉(zhuǎn)為攻擊或巡邏狀態(tài),而當(dāng)機(jī)器人處于無(wú)戰(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)入房子中搜集物資,看起來(lái)和旁人無(wú)疑,但早期的機(jī)器人是自動(dòng)生成生存物資的,為了降低游戲的復(fù)雜度,這里我將沿用其早期版本的用法。在機(jī)器人誕生之后一段時(shí)間后(給玩家收集物資的時(shí)間),則開(kāi)始進(jìn)行對(duì)機(jī)器人物資的生成,包括防具以及武器,而這里敵人的子彈是無(wú)限的,因此敵人不需要重復(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)除開(kāi)玩家和敵人,最為重要的就是整個(gè)游戲的自控系統(tǒng)。整個(gè)系統(tǒng)負(fù)責(zé)了游戲的進(jìn)程,以及除開(kāi)人物的所有的元素控制。譬如游戲玩家進(jìn)入飛機(jī)、空投的丟落、安全區(qū)的縮進(jìn),游戲的勝負(fù)條件以及我們之前所說(shuō)的機(jī)器人生成。4.4.1切換場(chǎng)景將戰(zhàn)斗場(chǎng)景和開(kāi)始場(chǎng)景分割開(kāi),可以防止游戲一開(kāi)始加載的資源過(guò)多導(dǎo)致的卡頓。首先需要將所有的場(chǎng)景添加到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)場(chǎng)景的名字傳入函數(shù)中調(diào)用即可切換場(chǎng)景,此腳本一般還需要在Awake函數(shù)中聲明加載新場(chǎng)景時(shí)不銷(xiāo)毀,可以避免多個(gè)場(chǎng)景重復(fù)掛載,同時(shí)還可以通過(guò)對(duì)SceneManager.sceneLoad事件添加委托,即可在每次加載新場(chǎng)景的時(shí)候刷新設(shè)置為不銷(xiāo)毀物體的某種屬性。4.4.2生成物體場(chǎng)景控制器也負(fù)責(zé)各角色和物資的生成,生成敵人的方法類(lèi)型,但為了保證敵人的隨機(jī)性,敵人的生成區(qū)域有多個(gè),因此生成時(shí)需要獲取場(chǎng)景中所有的敵人區(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;

}

}

}

}

}

以上代碼通過(guò)FindObjectOfType獲取所有擁有EnemySpawner的游戲物體,并且根據(jù)之前設(shè)置的機(jī)器人數(shù)量BotNumber,生成對(duì)應(yīng)數(shù)量的敵人。在生成結(jié)束后將敵人的戰(zhàn)斗狀態(tài)打開(kāi),開(kāi)始智能搜集物資的狀態(tài),物資的生成同理,參考有關(guān)玩家的生成。還有一種比較特殊的物體為飛機(jī)。用到飛機(jī)的場(chǎng)景是按時(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);

}

}

}

}這里類(lèi)似于生成敵人,也是獲取場(chǎng)景中的飛機(jī)生成點(diǎn)的游戲?qū)ο?,然后通過(guò)SpawnPoint()方法Random.insideUnitCircle返回一個(gè)單位圓的隨機(jī)向量,將向量標(biāo)準(zhǔn)化后乘于對(duì)應(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í)際上是通過(guò)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ì)通過(guò)調(diào)用玩家的用戶(hù)交互界面提示圈即將縮小的事件。

第五章屏幕后效5.1選中效果由于游戲場(chǎng)景中物體繁多,有可能會(huì)出現(xiàn)部分疊加在一起的情況,為了能夠更加直觀明確的看出是否選中了當(dāng)前物體,加入一個(gè)物體描邊的效果提示。物體選中以輪廓提示,一般是通過(guò)修改材質(zhì)來(lái)實(shí)現(xiàn),但是由于物體過(guò)多,逐個(gè)修改材質(zhì)未免有些繁瑣,所以這里選擇用屏幕后處理的方式實(shí)現(xiàn)。這種做法需要一個(gè)額外的攝像機(jī)專(zhuān)門(mén)用來(lái)渲染輪廓,同時(shí)需要設(shè)定對(duì)象為對(duì)應(yīng)的Layer,在該層級(jí)的問(wèn)題進(jìn)入描邊攝像機(jī)時(shí),即會(huì)對(duì)物體進(jìn)行處理,其本質(zhì)是對(duì)物體進(jìn)行模糊處理(兩次模糊、橫向縱向以此進(jìn)行高斯模糊),然后通過(guò)原始圖以及模糊圖計(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. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論