基于Unity3D的RPG解謎類游戲_第1頁
基于Unity3D的RPG解謎類游戲_第2頁
基于Unity3D的RPG解謎類游戲_第3頁
基于Unity3D的RPG解謎類游戲_第4頁
基于Unity3D的RPG解謎類游戲_第5頁
已閱讀5頁,還剩42頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

緒論1.1選題研究背景及意義隨著數(shù)字媒體技術(shù)的發(fā)展和人們審美水平的日益提高,數(shù)字游戲在集引人入勝的畫面、如夢似幻的聲音、扣人心弦的情節(jié)等要素于一身后,自成第九大藝術(shù)體。RPG(Role-PlayingGame)角色扮演游戲是許多玩家喜愛的游戲類型之一。玩家在游戲中扮演某個角色并遵循游戲世界中的規(guī)則,控制角色在游戲中進(jìn)行游戲活動,完成各種各樣的任務(wù)。RPG游戲不僅在娛樂方面展露頭角,而且廣泛運(yùn)用于各種領(lǐng)域,如教育教學(xué)的模擬,醫(yī)學(xué)解剖等。近年來,各種各樣的游戲?qū)映霾桓F,2014年UstwoGamesLtd開發(fā)的角色扮演解密類手機(jī)游戲“紀(jì)念碑谷”在游戲行業(yè)中熠熠生輝,2017年“紀(jì)念碑谷2”再創(chuàng)佳績。玩家在游戲中扮演公主艾達(dá),通過視覺錯位的關(guān)卡,隱秘的路徑來擊敗烏鴉人從而走出紀(jì)念碑迷陣。該游戲一問世,它就以其詩意的圖像和配樂而聞名。一款備受推崇的游戲離不開別出心裁的故事情節(jié),精妙絕倫的關(guān)卡設(shè)計(jì)以及美輪美奐的畫面和音效。游戲設(shè)計(jì)與開發(fā)的挑戰(zhàn)性就在于此,在游戲開發(fā)的過程中不僅要豐富玩家的游戲體驗(yàn),讓玩家身臨其境,而且要增強(qiáng)游戲的趣味性可玩性,能讓玩家沉浸于此并樂在其中。游戲開發(fā)離不開游戲引擎的支持。在眾多游戲引擎中,Unity3D是業(yè)內(nèi)廣泛使用的游戲引擎,Unity3D是丹麥開發(fā)的完全集成的專業(yè)游戲引擎,允許開發(fā)人員輕松創(chuàng)建多平臺游戲開發(fā)工具,尤其適用于開發(fā)3D游戲[1]。內(nèi)置編輯器,跨平臺部署,地形編輯,著色,碰撞器,腳本,網(wǎng)絡(luò),物理,UGUI框架,版本控制等功能可以為開發(fā)人員提供更多開發(fā)。Unity3D不僅界面簡單易用,功能易于運(yùn)行,而且配置文件版本對于開發(fā)人員來說是免費(fèi)的,而它也可以運(yùn)行在多個平臺上開發(fā)的游戲[2]。國內(nèi)3D游戲始于2003年,比國外3D游戲的開發(fā)晚得多。游戲開發(fā)和技術(shù)支持的概念存在不可逾越的差距[13]。目前,Unity3D游戲引擎在國內(nèi)和國際游戲產(chǎn)業(yè)中占據(jù)主導(dǎo)地位,其工作和功能對于游戲的未來發(fā)展和監(jiān)控游戲質(zhì)量具有重要意義[3]。由于此引擎具有:優(yōu)越的游戲表現(xiàn)力——粒子系統(tǒng)、后期渲染特效、可視化界面等為游戲的畫面感提供了強(qiáng)大的幫助,多平臺發(fā)布的簡單操作性,省去了底層編碼的環(huán)節(jié),縮短了游戲開發(fā)周期,降低開發(fā)成本。本項(xiàng)目是一款基于Unity3D引擎開發(fā)的RPG解謎類游戲“第七元素”,結(jié)合了典型的動作RPG游戲的人物操作競技性和打擊感以及解謎類游戲的寓教于樂的益智性和趣味性。1.2國內(nèi)外RPG游戲研究現(xiàn)狀國內(nèi)RPG游戲源形成于上世紀(jì)八十年代初的中國臺灣,此時歐美及日式RPG游戲如日中天,國內(nèi)游戲《軒轅劍》、《俠客英雄傳》等第一批劍俠RPG游戲誕生。國內(nèi)外RPG的形式由于地域文化差異而有所不同,比如歐美RPG游戲《上古卷軸》、《無冬之夜》、《巫師》;日式RPG游戲《勇者斗惡龍》、《最終幻想》,我國的RPG游戲源于古裝劍俠情愫,如《仙劍奇?zhèn)b傳》。西方RPG強(qiáng)調(diào)游戲自由,玩家通過與不同人物的對話以及執(zhí)行支線任務(wù)達(dá)到不同結(jié)局效果。而東方RPG強(qiáng)調(diào)旅途觀感體驗(yàn),玩家在游戲中與NPC有更多的互動,注重故事情節(jié)的多元化和游戲世界的氛圍。隨著全球互聯(lián)網(wǎng)的迅速發(fā)展,手機(jī)、電腦、平板電腦、游戲機(jī)等電子產(chǎn)品的快速迭代,預(yù)計(jì)到2020年全球游戲市場將達(dá)到最佳規(guī)模1285十億美元,與2016年274億美元的增長相比,將達(dá)到27.11%的增長幅度。中國、韓國和日本是三大最具規(guī)模的游戲市場,在該地區(qū)網(wǎng)民對游戲有強(qiáng)烈需求,游戲用戶的高滲透性,17年達(dá)到63.45%,在世界上排名第一[11]。到2016年,中國游戲市場的實(shí)際銷售收入1655.7億元,超過美國成為世界最大的電子游戲市場,在2017年,中國游戲產(chǎn)業(yè)的市場規(guī)模已超過200億人民幣。游戲產(chǎn)業(yè)已成為中國文化娛樂業(yè),對電子游戲的研究也從文化的內(nèi)涵、信息、通訊、教育學(xué)的角度,轉(zhuǎn)向經(jīng)濟(jì)和產(chǎn)業(yè)發(fā)展為主的方向[4]。與國外相比,中國的移動端游戲也正在成為文化產(chǎn)業(yè)的一個強(qiáng)有力的分支,如今,中國經(jīng)濟(jì)正在迅速增長,智能手機(jī)和4G網(wǎng)絡(luò)的迅速傳播為電子游戲的發(fā)展創(chuàng)造了良好的環(huán)境。從整體游戲行業(yè)來看,中國手機(jī)游戲正處于快速發(fā)展時期,玩家數(shù)量和市場規(guī)模持續(xù)保持穩(wěn)步的增長。根據(jù)國內(nèi)移動渠道代表硬核聯(lián)盟發(fā)布的報告顯示,2013年中國移動游戲異軍突起,手機(jī)游戲市場規(guī)模達(dá)到148.4億元。2014年,中國移動游戲市場規(guī)模達(dá)到276億元,而在過去的2015年,其市場規(guī)模高達(dá)407億元[15]。與此同時,國家正在積極支持游戲業(yè),以高效的方式創(chuàng)建與技術(shù)專業(yè)的發(fā)展相關(guān)的專業(yè),相信在不久的將來,我們自己的電子游戲?qū)殡S我們的生活,并將成為我國的支柱產(chǎn)業(yè)[12]。1.3研究內(nèi)容與研究框架本文經(jīng)過構(gòu)思整體游戲結(jié)構(gòu)、進(jìn)行需求分析、對各個模塊進(jìn)一步細(xì)化開發(fā),并結(jié)合3D游戲開發(fā)案例和網(wǎng)上學(xué)習(xí),基于Unity3D引擎設(shè)計(jì)開發(fā)了一款RPG解謎類游戲。其主要框架和內(nèi)容如下:第一章首先介紹了游戲行業(yè)的現(xiàn)狀,然后分析了該行業(yè)在國內(nèi)外的發(fā)展?fàn)顩r,最后闡述了本研究的背景和重要性。第二章對此項(xiàng)目的開發(fā)環(huán)境——Unity3D引擎進(jìn)行了簡單介紹,首先闡述了市場上主流的開發(fā)引擎Cocos2D-X,Unreal4,然后介紹了Unity3D引擎的特點(diǎn)。第三章是對游戲項(xiàng)目的設(shè)計(jì)和規(guī)劃,首先是游戲劇情的設(shè)定,其次對游戲需求進(jìn)行分析,最后進(jìn)行游戲功能模塊化的設(shè)計(jì)。第四章是對游戲的開發(fā)實(shí)現(xiàn),總體分為七個模塊:角色行為控制模塊,道具展示使用模塊,關(guān)卡邏輯模塊,UI交互展示模塊,攝像機(jī)控制模塊,音效模塊,最后是游戲后期特效處理的Shader模塊。第五章是對游戲的測試和優(yōu)化改進(jìn)。2開發(fā)環(huán)境2.1主流游戲引擎比較2.1.1Cocos2D-XCocos2D-X是二維多平臺便攜式游戲的開源平臺,可以用C++或Lua開發(fā)。并且可以在iOS,Android,Blackberry和其他操作系統(tǒng)上構(gòu)建并易于使用,還支持桌面操作系統(tǒng),如Windows,Mac和Linux。因此,開發(fā)人員編寫的源代碼很容易在桌面操作系統(tǒng)上進(jìn)行修改和更正。由于Cocos2d-x使用OpenGLES進(jìn)行圖形顯示,所以提高移動設(shè)備的圖形處理器性能較高。2.1.2UnrealUnreal(UNREALENGINE)是世界上最著名頂級的商業(yè)游戲引擎,占比全球80%的市場份額,很多大型的PC游戲的引擎都使用的虛幻引擎。EpicGames公司于2009年11月發(fā)布了虛幻引擎開發(fā)工具包UDK虛幻引擎。UDK不含源代碼,但包括UnrealEngine3引擎的獨(dú)立游戲開發(fā)中所有的工具,有些是非常昂貴的插件開發(fā)的中間件。由于這個原因,UDK虛幻3引擎,在游戲性能上表現(xiàn)突出[5]。UDK可供大家免費(fèi)使用,但是在商業(yè)發(fā)布之前需要花費(fèi)99美元購買授權(quán),如果發(fā)布的作品收入超過50000美元,則還需要支付超過部分的25%作為版稅[6]。2.2Unity3D引擎特點(diǎn)2.2.1Unity3D引擎開發(fā)框架 Unity3D工程都是由場景(Scene),2D或者3D的游戲?qū)ο螅℅ameObject),組件(Component)組成。完整的游戲可能有很多個場景組成,每個場景中有多個不同種類的游戲?qū)ο?,每個游戲?qū)ο笥刹煌墓δ芙M件組成。場景(Scene):游戲中可見的建筑物等整體的游戲世界,包括其中的所有游戲元素在內(nèi)。游戲?qū)ο螅℅ameOject):組成場景的游戲元素,如游戲中人物角色,房屋,植被等,是組成場景的各個部分。組件(Component):各個游戲?qū)ο蟮膶傩裕缛宋飳υ捒蛏蠏斓慕M件有RectTransform(可改變其平移,大小,錨點(diǎn)),Text(可設(shè)置對話文本的字體顏色大小等)。例如一個游戲角色屬于場景中的游戲?qū)ο?,掛在他身上的組件由Transform(可控制玩家的位移,旋轉(zhuǎn)和縮放),CharacterController(人物碰撞器組件:主要用于人物控制器。),Animator(動畫控制器組件:該組件需要引用AnimatorController,它定義了要使用的動畫片段,并控制何時以及如何在它們之間進(jìn)行混合和轉(zhuǎn)換。)2.2.2Unity3D引擎功能腳本腳本通常被理解為包含特定描述信息的可執(zhí)行文件,并以特定格式記錄。而在Unity3D中,游戲腳本一般是指繼承了MonoBehaviour類的一系列代碼文件。這些腳本代碼通??煽芍苯颖挥螒蛞嫠R別,并依照一定的生命周期規(guī)律來運(yùn)行,從而對游戲?qū)ο螽a(chǎn)生作用。[7]圖2-1Unity3D腳本的生命周期Unity3D腳本的生命周期如下:Awake():對象被實(shí)例化,事件被喚醒的時候執(zhí)行,只執(zhí)行一次。OnEnable():啟用腳本時啟用一次事件。Start():對象的第一幀時被調(diào)用的,標(biāo)志著腳背生命周期的開始,而且是在Update()之前。以上三個方法可用于初始化相關(guān)的操作。FixedUpdate():固定更新事件,執(zhí)行多次。每0.02s執(zhí)行一次,通常所有的物理組件相關(guān)的操作都在該事件中處理。Update():每幀執(zhí)行,可用于檢測玩家的操作輸入等,但當(dāng)游戲執(zhí)行比較復(fù)雜和繁瑣時不建議寫在此方法中,會影響游戲性能。LastUpdate():執(zhí)行次數(shù)比Update()方法多一次。OnDisable():禁用事件,在OnDestory()執(zhí)行之前執(zhí)行一次。禁用腳本組件時也會操作此方法。OnDestory():當(dāng)腳本的游戲?qū)ο蟊讳N毀時,會執(zhí)行一次該事件。聲明周期事件是由系統(tǒng)定義好的,且由系統(tǒng)調(diào)用。3游戲設(shè)計(jì)3.1游戲劇情設(shè)計(jì) RPG游戲引人入勝之處在于其豐富的故事情節(jié)和人物的可操作性。玩家通過控制虛擬世界中的游戲角色進(jìn)行游戲活動,在此過程中加入趣味性關(guān)卡設(shè)計(jì),畫面感和游戲場景的相互配合便能使游戲的可玩性得到極大的增強(qiáng)。 故宮博物館和網(wǎng)易攜手合作開發(fā)了一款把中國山水畫做成了解謎類的游戲《繪真妙筆千山》。游戲背景是由傳統(tǒng)的中國山水畫構(gòu)成,加入了很多中國風(fēng)元素,讓玩家在游戲中發(fā)現(xiàn)中國國粹的博大精深和藝術(shù)意義。于此同時,玩家必須在潺潺流水和裊裊炊煙的畫卷中找到更多的線索,解開謎題。[8]另一款游戲《彩虹墜入》是由NEXTStudio團(tuán)隊(duì)開發(fā)和制作,游戲畫風(fēng)具有非常統(tǒng)一和純粹的黑色、白色、光線概念,類似一部黑色童話小說,它用一種獨(dú)特的黑白技術(shù),營造了光感并留存在封陰影閉的空間。該游戲于2018年9月8日獲得“重識游戲——功能藝術(shù)游戲展”文化藝術(shù)傳播獎。[8]類似的優(yōu)秀游戲作品不勝枚舉。 本文開發(fā)的《第七元素》游戲是RPG解謎類游戲,受密室逃脫類游戲的啟發(fā),玩家在游戲中是一個受困于陰森神秘的中世紀(jì)教堂中的角色,通過尋找教堂中的各個聯(lián)系緊密的線索找尋通往自由的道路,最終實(shí)現(xiàn)自我救贖。 此項(xiàng)目中的游戲視覺使用了第三人稱,玩家通過移動跳躍鼠標(biāo)操作等行為動作觸發(fā)游戲中隱藏的線索,進(jìn)而獲取解謎關(guān)鍵的物件,開啟新的場景。游戲最后以玩家解開所有隱藏謎題,打開最后一扇門取勝。圖3-1游戲玩法策略圖3.2游戲需求分析與設(shè)計(jì) 根據(jù)以上游戲設(shè)計(jì)的玩法和策略可將游戲分為七個模塊。其需求分析如下:3.2.1角色模塊分析 游戲角色在虛擬世界中需要通過鍵盤控制其前進(jìn)左右移動、翻越障礙物的跳躍活動等,角色的控制應(yīng)該靈活自如使玩家控制起來可操作性強(qiáng)。 角色的動作由Unity3D自帶的Animator組件和動畫狀態(tài)控制機(jī)通過代碼來實(shí)現(xiàn)。3.2.2攝像機(jī)模塊分析 游戲中的視覺應(yīng)隨著角色的移動而變化,攝像機(jī)應(yīng)該實(shí)時檢測玩家位置、跟隨玩家的步伐,為了使游戲體驗(yàn)感良好,還應(yīng)該具備視野縮放,視野移動等功能。3.2.3關(guān)卡邏輯模塊分析 關(guān)卡邏輯在解謎游戲中的地位舉足輕重,動作元素和解謎元素始終要處于動態(tài)平衡的狀態(tài),即玩家操作控制復(fù)雜的動作時,解謎元素應(yīng)該簡單、可控性強(qiáng),而當(dāng)玩家操作簡單時,解謎元素比重就應(yīng)該有所增加。 整個解謎的過程應(yīng)該伴隨著動作元素和解謎元素的占比不同而有所變化。否則玩家會因?yàn)殡y以操作的動作和不知所云的謎題而煩躁不堪甚至對此游戲不再感興趣。3.2.4UI交互模塊分析 UI交互模塊應(yīng)包括信息提示和獲得物品的展示,即實(shí)時隨著觸發(fā)機(jī)關(guān)的時機(jī)而出現(xiàn)不同的消息提示機(jī)制,隨著獲取道具和消耗道具而在屏幕上出現(xiàn)或隱藏相應(yīng)的UI圖標(biāo)。 同時,還應(yīng)該讓玩家有交互體驗(yàn)的樂趣,比如圖紙可以在屏幕上由玩家自由拖動,或是鼠標(biāo)的圖標(biāo)隨著點(diǎn)擊的物品而變化成相應(yīng)的UI圖標(biāo)。3.2.5道具模塊分析 道具模塊是玩家獲取解謎信息的關(guān)鍵,通過獲取其中的一部分道具進(jìn)而產(chǎn)生與下一個線索的緊密聯(lián)系。道具出現(xiàn)的時機(jī)應(yīng)該隨著玩家觸發(fā)機(jī)關(guān)的時機(jī)而變化,同時,道具的使用也要具有一定的常理化,可交互性。3.2.6聲音模塊分析 音效是渲染游戲氛圍的重中之重,背景音樂的選擇一定要切合游戲的主題和類型,點(diǎn)擊UI圖標(biāo)和道具獲取時增加音效也會有事半功倍的效果。3.2.7Shader模塊分析 游戲酷炫的效果離不開特效的協(xié)助,Shader可以做出很多不錯的效果,因?yàn)樗遣逶阡秩竟艿览锩娴某绦?,一來是性能好,是GPU執(zhí)行的,不需要CPU再去做額外的處理,二來就是可控性強(qiáng),可以控制到每個頂點(diǎn),每個像素的著色。比如把一張圖片置灰,插入一個像素Shader,每個像素在紋理著色的時候把整個RGBA求一個灰度出來,這樣就變成一個灰色的圖片,這就是一個典型的像素Shader的使用。 Shader在游戲中使用屬于點(diǎn)睛之筆。3.3游戲特色1.游戲場景和畫面引人入勝 一款游戲在開始玩的時候,給人印象深刻的便是游戲場景的精美與否,比起粗糙的場景和UI,玩家更青睞與玩視覺體驗(yàn)感強(qiáng)的游戲。2.關(guān)卡設(shè)計(jì)鍛煉思維環(huán)環(huán)相扣的關(guān)卡設(shè)計(jì)可以激發(fā)玩家探索和解謎的好奇心,也能引發(fā)玩家從不同的角度去思考問題,拓寬思維。考驗(yàn)用戶的操作,可玩性特別高[14]。3.UI交互系統(tǒng)的樂趣性 玩家通過點(diǎn)擊不同道具的UI會使鼠標(biāo)的圖標(biāo)轉(zhuǎn)化為相應(yīng)的圖標(biāo)。增加玩家與游戲的互動性。4游戲?qū)崿F(xiàn)4.1角色模塊的實(shí)現(xiàn) 游戲角色人物Playman能通過用按鍵輸入控制其走跑跳躍的動作,人物游戲物體上有CharacterController組件,主要用于不使用剛體物理的第三人稱或第一人稱控制器。其行為動作的動畫是由組件Animator引用一個動畫狀態(tài)控制機(jī),由于人物移動較復(fù)雜,其行為動作動畫需要平滑過渡,所以在動畫控制狀態(tài)機(jī)內(nèi)加了行為混合樹,讓多個動畫的順接能平滑、自然過渡,其中的動畫切換用代碼寫了相應(yīng)的腳本組件掛在人物游戲物體上。圖4-1角色行為動畫混合樹圖4-2角色狀態(tài)混合樹參數(shù)設(shè)置面板 代碼控制原理:獲取按鍵輸入的水平垂直的位移對其進(jìn)行速度移動控制,當(dāng)速度大于某個特定值,向障礙物發(fā)射射線,射線碰撞到的物體的tag為“Obstacle”,當(dāng)射線距離大于一定值時,射線射到的位置來確定游戲人物左右手的高度,從而確定人物起跳的位置。Raycast(Vector3origin,Vector3direction,outRaycastHithitInfo,floatmaxDistance);//發(fā)射射線的方法。MatchTarget(Vector3matchPosition,QuaternionmatchRotation,AvatarTargettargetBodyPart,MatchTargetWeightMaskweightMask,floatstartNormalizedTime,[Internal.DefaultValue("1")]floattargetNormalizedTime);//這個方法就是讓動畫與目標(biāo)點(diǎn)進(jìn)行匹配,最終實(shí)現(xiàn)一些攀爬,跳躍一類的動作。4.2攝像機(jī)控制模塊實(shí)現(xiàn) 攝像機(jī)在游戲世界中是不可或缺的元素,它實(shí)時渲染著游戲中的物體的狀態(tài),玩家通過攝像機(jī)能看到游戲世界中的一切事物。在《第七元素》游戲中,攝像機(jī)實(shí)時跟隨玩家移動旋轉(zhuǎn),而在一個密閉的空間中,需要考慮的就是攝像機(jī)隨著人物移動到墻的轉(zhuǎn)角或是狹小的空間中時攝像機(jī)的視野不被遮擋,這樣才能讓玩家有良好的游戲體驗(yàn)。 此項(xiàng)目中,共有兩個腳本控制攝像機(jī)的行為,一個腳本是實(shí)時跟隨玩家且保證視野不被墻體遮擋。其原理是再定義幾個相機(jī)視野位置然后通過射線檢測來進(jìn)行判斷能否看到人物進(jìn)行相應(yīng)的調(diào)整。核心代碼如下:privatevoidUpdate(){Vector3beginPos=distance+player.transform.position;Vector3endPos=distance.magnitude*Vector3.up+player.transform.position;Vector3pos1=Vector3.Lerp(beginPos,endPos,0.25f);Vector3pos2=Vector3.Lerp(beginPos,endPos,0.5f);Vector3pos3=Vector3.Lerp(beginPos,endPos,0.75f);Vector3[]posArray=newVector3[]{beginPos,pos1,pos2,pos3,endPos};Vector3targetPos=posArray[0];for(inti=0;i<5;i++){RaycastHithitInfo;if(Physics.Raycast(posArray[i],player.transform.position-posArray[i],outhitInfo)){if(hitInfo.collider.tag!="Playman"){continue;}else{targetPos=posArray[i];break;}}else{targetPos=posArray[i];break;}}QuaternionnowRotation=transform.rotation;transform.LookAt(player.transform);transform.rotation=Quaternion.Lerp(nowRotation,transform.rotation,rotateSpeed*Time.deltaTime);transform.position=Vector3.Lerp(transform.position,targetPos,moveSpeed*Time.deltaTime);}其中endPos中distance.magnitude*Vector3.up表示為只要相機(jī)的高度Y坐標(biāo)通過加上人物的坐標(biāo)就是獲得人物正上方的坐標(biāo),將此坐標(biāo)設(shè)定為最差情況(相機(jī)豎直朝下拍攝),然后通過插值運(yùn)算對中間3個變量三維坐標(biāo)賦值,可以理解為由beginPos到endPos兩點(diǎn)之間形成的直線按照一定比例賦值,最后再用四元數(shù)和向量的插值運(yùn)算控制相機(jī)旋轉(zhuǎn)和位置移動(更加順滑過渡)。 另一個腳本控制攝像機(jī)視野的上下左右移動和視野縮放。核心代碼如下://點(diǎn)擊鼠標(biāo)左鍵進(jìn)行視野上下左右的移動if(Input.GetMouseButton(0)){if(axes==RotationAxes.MouseXAndY){floatrotationX=Camera.main.transform.localEulerAngles.y+Input.GetAxis("MouseX")*sensitivityX;rotationY+=Input.GetAxis("MouseY")*sensitivityY;rotationY=Mathf.Clamp(rotationY,minimumY,maximumY);Camera.main.transform.localEulerAngles=newVector3(-rotationY,rotationX,0);}elseif(axes==RotationAxes.MouseX){Camera.main.transform.Rotate(0,Input.GetAxis("MouseX")*sensitivityX,0);}else{rotationY+=Input.GetAxis("MouseY")*sensitivityY;rotationY=Mathf.Clamp(rotationY,minimumY,maximumY);Camera.main.transform.localEulerAngles=newVector3(-rotationY,Camera.main.transform.localEulerAngles.y,0);}}///按鼠標(biāo)滾輪縮放voidZoom(){//實(shí)現(xiàn)滑輪拖動floatfov=Camera.main.fieldOfView;fov+=-Input.GetAxis("MouseScrollWheel")*sensitivity;fov=Mathf.Clamp(fov,minFov,maxFov);Camera.main.fieldOfView=fov;}4.3關(guān)卡邏輯模塊的實(shí)現(xiàn) 邏輯級塊是游戲過程中不可或缺的一部分。邏輯的實(shí)現(xiàn)主要取決于碰撞檢測功能的實(shí)現(xiàn)。它們主要分為三個部分:第一部分是碰撞檢測:兩個游戲物體必須有碰撞,其中一個對象必須有一個Rigidbody組件。第二部分是觸發(fā)器觸發(fā)檢測:通過Unity3D內(nèi)置的Colider并檢查IsTrigger以獲取觸發(fā)器的狀態(tài)并應(yīng)用內(nèi)部封裝的碰撞檢測的方法。第三部分是觸發(fā)條件:通過確定邏輯值是否滿足觸發(fā)條件來獲得。這三部分相互補(bǔ)充,有機(jī)結(jié)合。4.3.1碰撞器模塊檢測 Collider:包含許多類型的一組組件,例如BoxCollider,MeshCollider等。這些碰撞的使用場景情況不同,但必須將它們添加到GameObjecet中。碰撞條件:每個對象碰撞必須具有碰撞并包含實(shí)體組件。 適用場景:模擬汽車被撞飛,皮球掉在地上又彈起的效果。 此項(xiàng)目中運(yùn)用場景:獲取圖紙時,與圖紙外面的容器發(fā)生碰撞檢測。容器承載圖紙游戲物體,如果勾選了IsTrigger,圖紙會穿透容器。所以容器游戲物體添加了Rigidbody,并且要確保游戲角色碰撞到它的時候位置不發(fā)生偏移,不發(fā)生旋轉(zhuǎn),所以要注意勾選Rigidbody組件的限制條件。圖4-1圖紙容器碰撞器設(shè)置4.3.2觸發(fā)器模塊檢測觸發(fā)器:在碰撞器組件中勾選IsTrigger屬性選擇框。圖4-2觸發(fā)器設(shè)置觸發(fā)信息檢測的系統(tǒng)自帶方法:1.MonoBehaviour.OnTriggerEnter(Collidercollider)當(dāng)進(jìn)入觸發(fā)器2.MonoBehaviour.OnTriggerExit(Collidercollider)當(dāng)退出觸發(fā)器3.MonoBehaviour.OnTriggerStay(Collidercollider)當(dāng)滯留觸發(fā)器項(xiàng)目中大部分收集物品或者是關(guān)卡觸發(fā)都用到觸發(fā)檢測。通過設(shè)置游戲物體碰撞器組件的長、寬、高以及位置等物理信息,從而設(shè)置物體的碰撞檢測的區(qū)域。IsTrigger勾選后可忽略對象的實(shí)際碰撞但可檢測到碰撞。即附加有該碰撞體的對象不會在物理上阻擋其他對象,但可檢測到是否與其他對象發(fā)生碰撞。[9] 如游戲中玩家與門發(fā)生碰撞時,掛在門上的腳本中的OnTriggerEnter方法對進(jìn)入到門觸發(fā)器的碰撞器進(jìn)行檢測,如果進(jìn)行碰撞的物體的tag為“Playman”,則UI界面的轉(zhuǎn)圈開門機(jī)關(guān)觸發(fā)。voidOnTriggerEnter(Collidercol){if(col.gameObject.tag=="Playman"){TurnPlate.gameObject.SetActive(true);}} 碰撞器和觸發(fā)器的不同之處:觸發(fā)器是依靠碰撞器提供碰撞檢測的基礎(chǔ)上進(jìn)行的觸發(fā)檢測,必須現(xiàn)有碰撞器才能有觸發(fā)器,即觸發(fā)器是碰撞器的一個屬性。區(qū)分使用的場景如需要檢測物體的運(yùn)動但是不影響物體本身的位置,采用觸發(fā)檢測;如果需要兩個物體的碰撞產(chǎn)生一定的實(shí)際效果,例如汽車撞墻等就需要碰撞器。4.3.3觸發(fā)條件模塊 以上兩種檢測方法在3D游戲中很常見,條件的判斷在編程中使用得非常普遍。延伸到觸發(fā)器系統(tǒng)中,同樣需要一組觸發(fā)條件來觸發(fā)相應(yīng)的事件,當(dāng)條件滿足時觸發(fā)事件,否則不會觸發(fā)相應(yīng)事件,實(shí)現(xiàn)觸發(fā)條件時使用布爾邏輯來進(jìn)行組合便擴(kuò)展該系統(tǒng)的使用。[9]觸發(fā)條件模塊幾乎涵蓋道具觸發(fā)的各個類,舉例如下:OpenChest類:掛在寶箱游戲物體上,用于判斷玩家當(dāng)前是否滿足開寶箱的條件,與觸發(fā)檢測聯(lián)合使用,當(dāng)玩家控制的游戲角色觸碰到寶箱時,判斷玩家當(dāng)前收集到的金幣數(shù)是否為7并且之前沒有開過寶箱,滿足以上兩個條件時執(zhí)行開寶箱操作。voidOnTriggerEnter(Collidercol){if(col.gameObject.tag.Equals("Playman")){if(Coin.coinCount>=1&&!didOpenChest){didOpenChest=true;chestTop.transform.rotation=Quaternion.Euler(newVector3(180,90,90));chestAll.SetActive(false);cameraFollw.SetActive(false);playman.SetActive(false);if(isUsedCoinsToOpenChestAction!=null){isUsedCoinsToOpenChestAction();}UnityEngine.SceneManagement.SceneManager.LoadScene(2);}else{openChestTip.DOFade(1,0.5f);openChestTipTex.DOFade(1,0.5f);StartCoroutine(disappearTip());}}}ScrollHolder類:掛在裝圖紙的容器游戲物體上,當(dāng)玩家鼠標(biāo)左鍵點(diǎn)擊并且點(diǎn)擊到UI上相應(yīng)的斧子圖標(biāo)時,執(zhí)行如下操作:從攝像機(jī)發(fā)射射線射到的物體的名字符合時,出現(xiàn)線索提示,容器設(shè)置為不可見,圖紙卷軸掉在地上。//通過射線檢測點(diǎn)擊3D物體,檢測其名字與tag是否與尋找的物體的相同if(Input.GetMouseButtonDown(0)&&ClickAxeImg.isClickImg){Rayray=Camera.main.ScreenPointToRay(Input.mousePosition);if(Physics.Raycast(ray,outhit)){obj=hit.collider.gameObject;if(.Equals("fi_vil_cath_wall_01")){openChestTipTex.text="Somethingdrops...";openChestTip.DOFade(1,0.3f);openChestTipTex.DOFade(1,0.3f);StartCoroutine(disappearTip());}}}4.4UI交互模塊的實(shí)現(xiàn) Unity3D中的UI架構(gòu)主要包括兩種,Unity引擎自帶的GUI和國外開發(fā)者開發(fā)的NGUI插件。而如今最受歡迎的是UGUI——Unity3D自帶的UI系統(tǒng),相較于NUUI來說更加操作簡單。圖4-3NUGI和UGUI比較 本項(xiàng)目使用的是UGUI系統(tǒng)即Unity3D內(nèi)置的UI編輯系統(tǒng)。它包括各種常用的UI控件,如按鈕(Button),文本框(Text),進(jìn)度條(Slider)等。此游戲的UI交互模塊可分為加載頁面UI模塊、開始游戲UI模塊、游戲進(jìn)行時UI模塊。具體實(shí)現(xiàn)如下:圖4-4游戲UI模塊4.4.1加載頁面 創(chuàng)建加載頁面的背景圖,自帶生成Canvas,Canvas是所有UI的父物體。Canvas下的CanvasScaler組件可以用來控制Canvas畫布下所有元素的縮放。GraphicRaycaster射線檢測組件,其作用是用于獲取用戶選中的UGUI控件,當(dāng)禁用這個組件的時候用戶在無法獲取到控件對控件進(jìn)行操作。 再創(chuàng)建游戲加載的進(jìn)度條(Slider),通過代碼對進(jìn)度條動畫進(jìn)行控制。首先在Start方法中對進(jìn)度條的值進(jìn)行初始化,游戲開始時保證進(jìn)度條始終從0開始加載,之后在Update里面對進(jìn)度條變化的值做動畫。privatevoidUpdate(){progressSlider.value+=Time.deltaTime;if(progressSlider.value==1){coverImg.GetComponent<CanvasGroup>().DOFade(0,1);}}4.4.2開始頁面 在開始頁面中添加開始游戲的按鈕控件,點(diǎn)擊按鈕時進(jìn)入游戲頁。其點(diǎn)擊事件如下:voidOnClickPlayBtn(){playBtn.GetComponent<RectTransform>().DOLocalMoveY(-343,0.1f);coverImg.DOFade(1,2f);UnityEngine.SceneManagement.SceneManager.LoadScene(1);}并在Start方法里通過按鈕點(diǎn)擊事件來響應(yīng)playBtn.onClick.AddListener(OnClickPlayBtn);4.4.3游戲進(jìn)行時UI實(shí)現(xiàn)1.提示UI: 當(dāng)觸發(fā)到場景中的一個道具線索時,提示信息會以圖片背景加提示文本的形式出現(xiàn),文本的內(nèi)容隨著觸發(fā)的游戲物體的不同而有不同的顯示。提示UI是使用了DoTween插件——一款強(qiáng)大的動畫編碼插件,很多的Unity3D游戲的動畫交互中大都用的這個插件??筛鶕?jù)不同的需求寫出不同的動畫效果,其中包括位置偏移、旋轉(zhuǎn)、縮放、UI通過改變透明度實(shí)現(xiàn)的漸隱漸現(xiàn)的效果,項(xiàng)目中場景切換的過渡就用到了此效果。提示UI的實(shí)現(xiàn)如下:voidStart(){openChestTip.DOFade(0,0f);openChestTipTex.DOFade(0,0f);axeImage.DOFade(0,0);}voidOnTriggerEnter(Collidercol){if(col.gameObject.tag.Equals("Playman")){openChestTipTex.text="Yougotaaxe";openChestTip.GetComponent<Image>().DOFade(1,0.3f);openChestTipTex.GetComponent<Text>().DOFade(1,0.3f);StartCoroutine(disappearTip());StartCoroutine(axeImageAnimation());}}IEnumeratordisappearTip(){yieldreturnnewWaitForSeconds(0.5f);openChestTip.GetComponent<Image>().DOFade(0,0.3f);openChestTipTex.GetComponent<Text>().DOFade(0,0.3f);}腳本開始作用時將提示UI的透明度設(shè)置為0,防止出現(xiàn)時機(jī)過早,當(dāng)出發(fā)到某一個線索物體時,將Text組件的text設(shè)置為提示內(nèi)容。并且透明度置為1。提示的信息持續(xù)時間有限,這里啟用了協(xié)程,將提示信息的持續(xù)時間設(shè)置為0.5秒,之后提示信息的圖片背景和文本內(nèi)容透明度設(shè)置為1。2.物品欄UI:物品欄UI圖標(biāo)的顯示和消失時機(jī)隨著觸發(fā)的游戲物體收集或使用時機(jī)而變化,物品的收集都是循序漸進(jìn)的,并且每個物品的UI的位置是根據(jù)前一個UI位置緊密排列,也就是說,前面物品的UI圖標(biāo)被使用并且消失后,后一個UI圖標(biāo)應(yīng)該往前挪,保證中間的位置不留空。所以物品收集和使用后都要對物品的UI進(jìn)行位置的判斷和移動。具體的消息傳遞機(jī)制由收集到的鑰匙來舉例: GetKey是掛在鑰匙游戲物體上的腳本組件,當(dāng)玩家控制游戲角色與鑰匙發(fā)生碰撞時收集到鑰匙,鑰匙物體的激活狀態(tài)為false,并且出現(xiàn)提示UI,"Igotakey."s具體實(shí)現(xiàn)如下:[SerializeField]privateTexttipTex;[SerializeField]privateImagetip;publicstaticboolisGetKey;publicstaticActionisUsedScrollAction;voidStart(){tip.DOFade(0,0f);tipTex.DOFade(0,0f);}voidOnTriggerEnter(Collidercol){if(col.gameObject.tag=="Playman"){tipTex.text="Igotakey.";if(isUsedScrollAction!=null){isUsedScrollAction();}tip.DOFade(1,0.3f);tipTex.DOFade(1,0.3f);isGetKey=true;StartCoroutine(delay());}}IEnumeratordelay(){yieldreturnnewWaitForSeconds(1f);tip.DOFade(0,0.3f);tipTex.DOFade(0,0.3f);gameObject.SetActive(false);} 當(dāng)管理UI腳本DontDestroyTool類中Update方法中獲取到收集到鑰匙的布爾條件為ture時,再判斷前面收集到的物品是否被使用,如果沒有使用,則收集到的鑰匙排在其后面,否則往前挪一個位置。物體UI圖標(biāo)收集到時使用了DoTween動畫,提示玩家收集到了此物品。具體實(shí)現(xiàn)如下:if(GetKey.isGetKey){if(icon2Image.IsActive()){icon2RectTram.anchoredPosition=newVector2(icon2RectTram.anchoredPosition.x-150,icon2RectTram.anchoredPosition.y);StartCoroutine(imageToIconAnimation(keyRectTram,icon2RectTram,150,keyImage));}else{//key前面沒有icon2則是第一個StartCoroutine(noPreviousRec(keyRectTram,0,keyImage));}GetKey.isGetKey=false;}物品UI的動畫用的是同一個方法,將物品UI的錨點(diǎn)設(shè)置在屏幕中間,放大和移動的動畫同時播放,循環(huán)3次。IEnumeratorimageToIconAnimation(RectTransformrect,RectTransformpreviousRec,floatdistance,Imageimg){yieldreturnnewWaitForSeconds(0.03f);iconObj.SetActive(false);rect.anchoredPosition=Vector2.zero;rect.anchorMax=newVector2(0.5f,0.5f);rect.anchorMin=newVector2(0.5f,0.5f);Sequenceseq=DOTween.Sequence();seq.Append(rect.DOScale(Vector3.one*4,0.5f).SetEase(Ease.InOutCirc)).Append(rect.DOLocalMove(newVector3(previousRec.anchoredPosition.x+distance,previousRec.anchoredPosition.y,0),0.2f)).Append(rect.DOScale(Vector3.one*2f,0.2f).SetEase(Ease.InOutCirc)).Append(rect.DOScale(Vector3.one,0.2f).SetEase(Ease.InOutCirc).SetLoops(3));img.gameObject.SetActive(true);}3.觸發(fā)關(guān)卡UI 每次收集到的物品會轉(zhuǎn)變?yōu)閁I放置在屏幕左下角,鼠標(biāo)點(diǎn)擊不同的UI時圖標(biāo)會發(fā)生相應(yīng)的變化。再次點(diǎn)擊,鼠標(biāo)會恢復(fù)成原本圖標(biāo)。 第二道門的開門觸發(fā)是游戲關(guān)卡的核心,這里是游戲進(jìn)度的分水嶺。圖4-5放入三枚徽章的前后對比收集到的三枚徽章點(diǎn)擊相應(yīng)圖標(biāo)后放到對應(yīng)的位置,三個位置是按鈕控件,當(dāng)對應(yīng)的布爾條件滿足時,三個位置未激活的圖標(biāo)設(shè)置為激活狀態(tài),具體實(shí)現(xiàn)代碼如下:voidClickPointerLeft(){if(ClickIcon1Img.isClickIcon1Img){ClickKeyImage.isClickImg=false;blueImg.gameObject.SetActive(true);Cursor.SetCursor(normalMouseTex,Vector2.zero,CursorMode.Auto);isPlaceIcon1=true;if(isUsedIcon1!=null){isUsedIcon1();}}}voidClickPointerRight(){if(ClickIcon2Img.isClickIcon2Img){ClickKeyImage.isClickImg=false;purpleImg.gameObject.SetActive(true);Cursor.SetCursor(normalMouseTex,Vector2.zero,CursorMode.Auto);isPlaceIcon2=true;if(isUsedIcon2!=null){isUsedIcon2();}}}voidClickPointerUp(){if(ClickIcon3Img.isClickIcon3Img){ClickKeyImage.isClickImg=false;yellowImg.gameObject.SetActive(true);Cursor.SetCursor(normalMouseTex,Vector2.zero,CursorMode.Auto);isPlaceIcon3=true;if(isUsedIcon3!=null){isUsedIcon3();}}}圖4-6第一、二次旋轉(zhuǎn)到正確位置對比并點(diǎn)擊中間的按鈕發(fā)生相應(yīng)的旋轉(zhuǎn)角度,記錄點(diǎn)擊次數(shù),每次旋轉(zhuǎn)的角度通過旋轉(zhuǎn)次數(shù)*固定角度得來。具體代碼實(shí)現(xiàn)如下:voidClickTurnCenter(){if(shouldTurn()){clickTurnCount++;centerBtn.transform.rotation=Quaternion.Euler(newVector3(0,0,-10*clickTurnCount));blueImg.transform.rotation=Quaternion.Euler(newVector3(0,0,5*clickTurnCount));purpleImg.transform.rotation=Quaternion.Euler(newVector3(0,0,5*clickTurnCount));yellowImg.transform.rotation=Quaternion.Euler(newVector3(0,0,5*clickTurnCount));}} 當(dāng)中間按鈕旋轉(zhuǎn)的z軸為-0.5或者0.5時,第一次旋轉(zhuǎn)到正確的位置,三個不規(guī)則三個圖形的父物體上添加CanvasGroup組件,可對其子物體統(tǒng)一做透明度動畫。 當(dāng)?shù)谝淮握_旋轉(zhuǎn)發(fā)生并且中間按鈕旋轉(zhuǎn)的z軸為1或者-1時,第二次旋轉(zhuǎn)到正確的位置,中間橙色光圈的大小從0變到1,透明度也從0變到1。通過協(xié)程停頓2.5秒后旋轉(zhuǎn)的UI透明度變?yōu)?后變?yōu)槲醇せ顮顟B(tài),發(fā)送消息給門的腳本組件,之后門打開,門口的燈由紅色變?yōu)榫G色。voidTurnSuccessFirst(){if(centerBtn.transform.rotation.z==-0.5f||centerBtn.transform.rotation.z==0.5f){IrregularShapes.gameObject.SetActive(true);IrregularShapes.alpha+=Time.deltaTime;blueImg1.gameObject.SetActive(true);purpleImg1.gameObject.SetActive(true);yellowImg1.gameObject.SetActive(true);blueImg1.transform.rotation=Quaternion.Euler(newVector3(0,0,60));purpleImg1.transform.rotation=Quaternion.Euler(newVector3(0,0,60));yellowImg1.transform.rotation=Quaternion.Euler(newVector3(0,0,60));turnSuccessFirst=true;}TurnSuccessSecond();}IEnumeratorTurnSuccessSecond(){if(turnSuccessFirst){if(centerBtn.transform.rotation.z==1||centerBtn.transform.rotation.z==-1f){blueImg1.transform.rotation=Quaternion.Euler(newVector3(0,0,-60));purpleImg1.transform.rotation=Quaternion.Euler(newVector3(0,0,-60));yellowImg1.transform.rotation=Quaternion.Euler(newVector3(0,0,-60));Sequencesequence=DOTween.Sequence();sequence.Append(lightImg.GetComponent<RectTransform>().DOScale(Vector3.one*0.9f,2)).Insert(0,lightImg.DOFade(1,2));yieldreturnnewWaitForSeconds(2.5f);TurnTable.DOFade(0,0.5f).OnComplete(()=>{TurnTable.gameObject.SetActive(false);if(isSuccessRiddleAction!=null){isSuccessRiddleAction();}});}}}4.5道具模塊的實(shí)現(xiàn) 金幣:玩家控制游戲角色跑、跳躍等動作行為收集7枚金幣,每個金幣游戲物體上都掛有Coin腳本組件和碰撞器,與游戲角色發(fā)生碰撞檢測時收集金幣,金幣數(shù)加一。 寶箱:掛有OpenChest腳本組件和碰撞器。當(dāng)游戲角色與寶箱碰撞時,判斷收集到的金幣數(shù)是否為7并且是第一次開箱,兩個條件滿足時,跳轉(zhuǎn)開寶箱場景,主游戲頁的玩家和攝像機(jī)激活狀態(tài)為false,收集到一枚徽章。如果兩個條件都不滿足則出現(xiàn)提示文本信息。 斧子:只有在開寶箱事件觸發(fā)后,斧子游戲物體才會出現(xiàn)在游戲場景中。斧子游戲物體上掛有GetAxe腳本組件和碰撞器組件,當(dāng)游戲角色與斧子發(fā)生碰撞檢測時收集到斧子。并且斧子圖標(biāo)UI出現(xiàn)在屏幕上。 圖紙卷軸的容器:掛有ScrollHolder腳本組件和碰撞器組件,當(dāng)游戲角色與其發(fā)生碰撞時,出現(xiàn)提示線索信息,玩家需要點(diǎn)擊屏幕上的斧子圖標(biāo),隨即鼠標(biāo)圖標(biāo)變成相應(yīng)的游戲物體的UI,然后點(diǎn)擊圖紙卷軸的容器,其觸發(fā)條件必須滿足點(diǎn)擊了斧子UI和鼠標(biāo)點(diǎn)擊時的射線檢測到的物體名字是容器的名字。之后容器消失,卷軸落下。 圖紙卷軸:當(dāng)鼠標(biāo)點(diǎn)擊卷軸時出現(xiàn)提示線索文本,只有按住鼠標(biāo)左鍵把圖紙拖動到藍(lán)色光線照耀的區(qū)域才能觸發(fā)線索。此處將光線照耀的區(qū)域加了空物體并掛上碰撞器,卷軸碰撞器與其碰撞進(jìn)入LookPaper場景,收獲到一枚徽章和一個圖紙卷軸。 六個瓶子:玩家控制游戲角色按照圖紙卷軸上的順序把瓶子打破,觸發(fā)線索機(jī)關(guān),羅馬數(shù)字7的位置上建筑物石柱向下位移,鑰匙出現(xiàn)。 鑰匙:掛有GetKey腳本組件和碰撞器組件,當(dāng)游戲角色與鑰匙游戲物體發(fā)生碰撞時收集到鑰匙,并且屏幕左下角出現(xiàn)相應(yīng)的鑰匙物品的UI。 第一扇門:開門的條件必須滿足兩者:玩家點(diǎn)擊鑰匙UI鼠標(biāo)圖標(biāo)變成鑰匙UI圖標(biāo),鼠標(biāo)左鍵點(diǎn)擊時發(fā)射射線檢測到的物體名字是門,此時門打開,門口的燈光顏色從藍(lán)色變成綠色。 拖把:進(jìn)門左手邊的墻角有一個拖把,當(dāng)玩家與其發(fā)生觸發(fā)檢測時收集到該物體。 書:進(jìn)門右手邊屋子的桌子上放置這一本書,與其發(fā)生觸發(fā)檢測會出現(xiàn)提示線索信息,鼠標(biāo)左鍵點(diǎn)擊并且判斷是否開了門才能獲取該物體。 徽章三:進(jìn)門一直往前的屋子里會發(fā)現(xiàn)一塊壁畫與其他三塊不一樣,上面沾滿了污漬,用收集到的拖把進(jìn)行清潔:點(diǎn)擊拖把UI圖標(biāo),再點(diǎn)擊壁畫,此時進(jìn)入清潔壁畫的場景,主場景的游戲人物和攝像機(jī)暫時未激活。每點(diǎn)擊一次壁畫,覆蓋在上面的污漬材質(zhì)圖片的透明度就降低,直到透明度為0時,游戲人物和攝像機(jī)設(shè)置為激活狀態(tài),此時點(diǎn)擊徽章三收集。此處代碼實(shí)現(xiàn)如下:voidUpdate(){if(Input.GetMouseButtonDown(0)){Debug.Log("pressmouse.");ripple.Emit(Vector2.one);clickMouseNum++;deduceStains(clickMouseNum);}if(material.color.a<=0){isClearedStains=true;transform.gameObject.SetActive(false);Cursor.SetCursor(normalMouseTex,Vector2.zero,CursorMode.Auto);if(isUsedBroom!=null){isUsedBroom();}}}voiddeduceStains(floatcount){floatalph=1-0.3f*count;material.color=newColor(0,0,0,alph);}當(dāng)污漬透明度<=0時,回調(diào)函數(shù)執(zhí)行如下:voidhideBroomImage(){broomImage.gameObject.SetActive(false);stainsObj.SetActive(false);icon3Obj.SetActive(false);cameraFollw.SetActive(true);playman.SetActive(true);bookRectTram.anchoredPosition=newVector3(bookRectTram.anchoredPosition.x–150,bookRectTram.anchoredPosition.y,0);}第二道門:將收集到的三枚徽章放入轉(zhuǎn)盤的相應(yīng)位置,點(diǎn)擊中間旋轉(zhuǎn)觸發(fā)開門事件,此時門外的紅燈變?yōu)榫G燈。 書柜上的書:滿足三個條件才能觸發(fā)——玩家收集到了前面房間桌子上的書、碰撞到了書柜、第一次碰撞到書柜。如果滿足條件則進(jìn)入TriggerBook場景,此時書本的UI圖標(biāo)透明度變?yōu)?,書本游戲物體從UI的位置發(fā)生位移、放大、旋轉(zhuǎn)三個動畫同時作用,書本最后移動到缺失的位置,過了兩秒之后,一排的書整體移動,開門機(jī)關(guān)出現(xiàn)。具體動畫實(shí)現(xiàn)代碼如下:IEnumeratorbookIsShow(){bookImgShouldHide=true;yieldreturnnewWaitForSeconds(2);TransformbookTran=book.GetComponent<Transform>();Sequencesequence=DOTween.Sequence();sequence.Append(bookTran.DOScale(Vector3.one,1)).Insert(0,bookTran.DOLocalRotate(newVector3(0,-90,0),0.5f,RotateMode.Fast)).Insert(0,bookTran.DOLocalMove(newVector3(-0.03f,-0.008f,0.258f),2f).SetEase(Ease.OutQuint));yieldreturnnewWaitForSeconds(2);book.transform.parent.GetComponent<Transform>().DOLocalMoveZ(42f,2).SetEase(Ease.InCubic);bookIsMove=true;} 開門機(jī)關(guān):鼠標(biāo)左鍵點(diǎn)擊并且書移動的條件滿足后,開門機(jī)關(guān)發(fā)生旋轉(zhuǎn),開門的條件滿足。 第三道門:玩家需要控制游戲角色與門發(fā)生觸發(fā)檢測并且開門機(jī)關(guān)觸發(fā)后才可以開門。 墨水瓶:游戲人物與墨水瓶發(fā)生觸發(fā)檢測,收集到4個墨水瓶。 箱子:游戲人物與其碰撞并且滿足收集到的墨水瓶數(shù)量>=4,可觸發(fā)機(jī)關(guān),箱子的圖標(biāo)變亮,并且獲得火柴道具。 走道上的油燈:玩家需要點(diǎn)擊屏幕左下角的火柴UI圖標(biāo),當(dāng)鼠標(biāo)圖標(biāo)變成火柴時,點(diǎn)擊油燈游戲物體,此時點(diǎn)燃油燈,開第四道門的條件滿足。 第四道門:游戲人物與門發(fā)生觸發(fā)檢測,并且點(diǎn)燃油燈方可開門。 書本:點(diǎn)擊放在桌子上的書本,進(jìn)入ClickBook場景,記住上面的數(shù)字。 圖紙:收集到羽毛筆后方可觸發(fā),之后進(jìn)入MapClue場景。 第五道門:根據(jù)兩個線索找出開門密碼,游戲成功。4.6聲音模塊 Unity3D播放音樂方便快捷,使用其自帶的AudioSource組件,把需要播放的音效放到組件的AudioClip里,根據(jù)需求調(diào)整組件的參數(shù)設(shè)置。圖4-7AudioSource組件及其參數(shù)設(shè)置 本項(xiàng)目的音效分為UI交互音效、道具音效和背景音樂。UI交互音效的播放時機(jī)是在點(diǎn)擊按鈕時,進(jìn)入游戲的打字機(jī)動畫效果和音效的播放使用了DoTween動畫里的text.DoText,當(dāng)文本動畫播放完之后使用回調(diào)函數(shù),讓音效停下。具體實(shí)現(xiàn)代碼如下:text.DOText("Icametothemedievalchurchalone."+"\n"+"\n"+"Suddenlyclosedthedoor..."+"\n"+"\n"+"Ihavetofindthedoortogoout...",10f).OnComplete(()=>{TextAud.Stop();});按任意鍵開始游戲時,音效停止播放。privatevoidUpdate(){if(Input.anyKey){TextAud.Stop();coverImg.DOFade(0,0.5f);}} 背景音樂放在游戲角色的AudioSource組件里,隨著角色移動播放,這樣做的好處就是不管角色走到哪里,音樂的聲音大小都是一致的,不會忽遠(yuǎn)忽近。 獲取道具時播放的音效隨著不同道具被觸發(fā)而播放不同的聲音,有助于增加游戲的真實(shí)性,讓玩家身臨其境。4.7Shader模塊 Shaderlanguage,稱為著色語言,是一種高級語言,但必須基于圖形硬件,用來對三維圖形進(jìn)行光影,空間位置變換,顏色處理等操作,最終改變物體的形狀、大小、位置以及實(shí)現(xiàn)特效,在實(shí)時變化的游戲、電影中模擬真實(shí)、非真實(shí)的畫面效果。 本項(xiàng)目共有兩個地方用到了Shader,一處是開始游戲頁面的Play按鈕,具體的Shader代碼如下:Shader"UI/UpdateBrightness"{Properties{_Color("MainColor",Color)=(1,1,1,1)_MainTex("Base(RGB)",2D)="white"{}_Brightness("Brightness",Range(-1,1))=0}SubShader{Tags{"Queue"="Transparent"}Pass{CullOffLightingOffZWriteOffBlendSrcAlphaOneMinusSrcAlphaCGPROGRAM#pragmavertexvert#pragmafragmentfrag#include"UnityCG.cginc"float4_Color;sampler2D_MainTex;float_Brightness;structv2f{float4pos:SV_POSITION;float2uv:TEXCOORD0;};float4_MainTex_ST;v2fvert(appdata_basev){v2fo;pos=UnityObjectToClipPos(v.vertex);uv=TRANSFORM_TEX(v.texcoord,_MainTex);returno;}floatBrightenChannel(floatc,floatbrightness){if(brightness<0){returnc+c*brightness;}else{returnc+c*(1/(1-brightness)-1);}}half4frag(v2fi):COLOR{half4texcol=tex2D(_MainTex,i.uv);half4finalColor=texcol;finalColor*=_Color;finalColor.r=BrightenChannel(finalColor.r,_Brightness);finalColor.g=BrightenChannel(finalColor.g,_Brightness);finalColor.b=BrightenChannel(finalColor.b,_Brightness);returnfinalColor;}ENDCG}}Fallback"VertexLit"}在Properties塊里定義參數(shù),可以在可視面板上調(diào)整參數(shù)可視化看最終畫面中的效果,比如調(diào)整主要顏色“_Color”,更換圖片“_MainTex”,修改亮度值“_Brightness”。然后在LetMeGoBrightenEffect腳本組件中對亮度值進(jìn)行DoTween補(bǔ)間動畫://對currentBrightness做DoTween動畫voidstartTweenBrightValue(){Sequencese=DOTween.Sequence();se.AppendInterval(preTime);for(inti=0;i<animationCount;i++){se.Append(DOTween.To(()=>currentBrightness,x=>currentBrightness=x,brightnessTo,0.4f)).SetEase(Ease.

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論