工程實訓說明書-基于Unity的3D機器人探險游戲_第1頁
工程實訓說明書-基于Unity的3D機器人探險游戲_第2頁
工程實訓說明書-基于Unity的3D機器人探險游戲_第3頁
工程實訓說明書-基于Unity的3D機器人探險游戲_第4頁
工程實訓說明書-基于Unity的3D機器人探險游戲_第5頁
已閱讀5頁,還剩35頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

文檔可自由編輯打印文檔可自由編輯打印文檔可自由編輯打印XXXX工程實訓說明書題目系(部)計算機科學與技術專業(yè)(班級)姓名學號指導教師起止日期2014.06.11-2014.07.05摘要本次工程實訓的實訓題目是基于Unity的3D機器人探險游戲。Unity是一款很強大3D游戲開發(fā)引擎。在用Unity實現(xiàn)3D機器人游戲的過程中,在軟件使用方面,需要用到photoshop和3Dmax等美工或建模軟件;在腳本語言編寫方面,需要涉及JS或C#;本說明書從最初的3D探險游戲策劃,到利用Unity相關技術實現(xiàn)場景物體繪制及渲染,再到3D探險游戲的測試,最后到游戲的完全實現(xiàn)及單機版的發(fā)布,對本次實訓內(nèi)容的實現(xiàn)和完成過程進行描述和說明。Unity探險游戲主要包括如下內(nèi)容:場景、檢查點、widget機器人、敵方角色。檢查點用于widget機器人在游戲過程中的死亡后的復活。關鍵字:Unity,3D,JS,C#目錄TOC\o"1-3"\h\u摘要 I1 引言 11.1編寫目的 11.2項目背景 12 需求規(guī)約 32.1任務概述 32.2需求規(guī)定 32.3運行環(huán)境規(guī)定 53 游戲?qū)崿F(xiàn)過程 63.1游戲玩法設計 63.2游戲內(nèi)容設計 63.3游戲界面設計 63.4關卡設計 103.5游戲基本架構(gòu)和主要類設計 113.6數(shù)據(jù)結(jié)構(gòu)與算法設計 134 技術說明 154.13D渲染 154.2動畫制作 154.3數(shù)據(jù)存儲 154.4游戲特效 154.5粒子系統(tǒng) 154.6碰撞檢測的實現(xiàn) 164.7游戲AI 165 測試用例設計 185.1測試用例編寫目的 185.2測試用例 185.3測試總結(jié)和改進建議 20總結(jié) 21參考文獻 22附錄游戲核心代碼 23(1)機器人的角色控制核心代碼 23(2)機器人的狀態(tài)處理核心代碼 26(3)AI控制核心代碼 28(4)拾取物品和背囊管理核心代碼 32(5)碰撞檢測核心代碼 35引言1.1編寫目的本文檔是進行項目策劃、概要設計和詳細設計的基礎,也是編寫測試用例和進行系統(tǒng)測試的主要依據(jù)。同時,該文檔也是用戶確定軟件功能需求的主要依據(jù)。本文檔的讀者對象很多,例如,項目經(jīng)理、設計員、程序員、測試員、銷售員、用戶、其他人員如公司領導等。因此,運用Unity進行3D探險游戲開發(fā)的開發(fā)人員在進行開發(fā)之前,需要仔細閱讀該文檔,明確需求分析,并對場景構(gòu)思有較好的理解。1.2項目背景1.2.1Unity簡介Unity是一款跨平臺的游戲開發(fā)工具,從一開始就被設計成易于使用的產(chǎn)品。作為一個完全集成的專業(yè)級應用,Unity還包含了價值數(shù)百萬美元的功能強大的游戲引擎。Unity3D是一個讓你輕松創(chuàng)作的多平臺的游戲開發(fā)工具,是一個全面整合的專業(yè)游戲引擎。1.2.2項目背景簡介本項目的名稱為用Unity進行3D探險游戲開發(fā)。由軟件工程(數(shù)字媒體)教研室提出,有數(shù)字媒體方向?qū)W生具體實現(xiàn),實現(xiàn)過程包括:游戲策劃、場景設計、3D建模、渲染貼圖、測試、用戶體驗等。進入21世紀后,游戲動漫設計已經(jīng)成為全球十分熱門的行業(yè)。游戲動漫產(chǎn)業(yè)的巨大影響力不僅凸顯在我們的生活中,其發(fā)展過程中產(chǎn)生的經(jīng)濟效益也吸引了越來越多投資者的眼光,成為了新一輪經(jīng)濟發(fā)展的增長點。而本次工程實訓3D場景渲染的開發(fā),最終將獲得一個小型的游戲或動漫3D場景,而現(xiàn)在的游戲或動漫中3D產(chǎn)品已經(jīng)成為主流。飛速發(fā)展的游戲和動漫產(chǎn)業(yè)在市場上已經(jīng)帶來了非??捎^的收益。從市場規(guī)模來看,2009年中國網(wǎng)絡游戲市場規(guī)模達到258億元人民幣,同比增長39.5%。其中:國產(chǎn)網(wǎng)絡游戲市場規(guī)模達到157.8億元人民幣,比2008年增長41.9%,占總體市場規(guī)模的61.2%。從主要細分游戲市場來看:大型多人同時在線角色扮演游戲(MMORPG)是市場的主導力量,2009年MMORPG占整體網(wǎng)絡游戲市場的比例約為79%,市場規(guī)模達到203.8億元,較2008年增長35.2%;高級休閑游戲(ACG)的增長速度在加快,2009年高級休閑游戲占總體網(wǎng)絡游戲市場規(guī)模的比例約為13.8%,市場規(guī)模達到35.5億元,較2008年增長49.7%。因此,作為數(shù)字媒體專業(yè)的學生,在畢業(yè)前接觸相關的游戲或動漫開發(fā)的案例,有利于熟悉游戲或動漫的開發(fā)流程,能為以后從事游戲或動漫方向的就業(yè)打下良好的基礎。需求規(guī)約需求規(guī)約包括任務概述、需求規(guī)定、運行環(huán)境規(guī)定三個部分。任務概述將對Unity的3D探險游戲需要完成的任務做簡要說明;需求規(guī)定將從業(yè)務需求方面對3D探險游戲的實現(xiàn)進行需求分析;運行環(huán)境規(guī)定,即實現(xiàn)3D探險游戲場景渲染需要的硬件和軟件支持。2.1任務概述Unity3D是由UnityTechnologies開發(fā)的一個讓玩家輕松創(chuàng)建諸如三維視頻游戲、建筑可視化、實時三維動畫等類型互動內(nèi)容的多平臺的綜合型游戲開發(fā)工具,是一個全面整合的專業(yè)游戲引擎。Unity類似于Director,Blendergameengine,Virtools或TorqueGameBuilder等利用交互的圖型化開發(fā)環(huán)境為首要方式的軟件其編輯器運行在Windows和MacOSX下,可發(fā)布游戲至Windows、Mac、Wii、iPhone和Android平臺。也可以利用Unitywebplayer插件發(fā)布網(wǎng)頁游戲手機游戲支持Mac和Windows的網(wǎng)頁瀏覽。本次實訓的題目為基于Unity3D的機器人探險游戲技術實現(xiàn),旨在成功的設計出一款可以運行在智能手機和平板電腦上的探險游戲。該項目主要界面和功能包括:(1)界面設計的美觀有一種三維仿真的效果。(2)系統(tǒng)中的模型進行移動和碰撞檢測。(3)場景中的樹實現(xiàn)風吹動的效果。(4)機器人對小兔子的攻擊(5)拾取功能、背囊管理。2.2需求規(guī)定2.2.1對功能的規(guī)定本項目主要功能有:開始游戲,幫助,退出游戲,機器人的移動控制,背囊管理,小兔子的AI控制。開始游戲,loading后用戶進入游戲。表1游戲功能表編號功能名稱使用角色功能描述輸入系統(tǒng)響應輸出1開始游戲玩家點擊按鈕用戶進入游戲選擇模式按鈕輸入彈出游戲模式按鈕2幫助玩家點擊按鈕用戶進入游戲幫助按鈕輸入進入游戲幫助3退出游戲玩家點擊按鈕用戶退出游戲,游戲結(jié)束按鈕輸入退出游戲,游戲結(jié)束4機器人的移動控制玩家Wasd鍵控制機器人的移動鍵盤輸入根據(jù)玩家的輸入機器人移動5背囊管理NPC保存玩家找到的獎品無獎品保存到背囊中6小兔子的AI控制NPC控制小兔子的狀態(tài)無小兔子的運動狀態(tài)2.2.2對界面的規(guī)定本項目涉及界面包括開發(fā)菜單界面,游戲界面。菜單界面用于顯示游戲的菜單,包括開始游戲,退出游戲。游戲界面用于3D顯示游戲的各個場景,物體,地形等元素。2.2.3故障處理要求軟件可能出現(xiàn)的故障:表2游戲故障預測表故障類型故障處理機器人無法正常操作重新運行2.3運行環(huán)境規(guī)定2.3.1硬件要求操作系統(tǒng)(Windows)XP、Vista32位、Win7。CPU主頻P4

1.4GHz及以上。內(nèi)存256MB以上。顯存支持獨立、集成顯卡,要求顯存32MB以上。硬盤大小2.2GB以上。屏幕分辨率800*600及以上。2.3.2軟件要求Unity4.0或4.0以上版本,photoshop和3Dmax等設計或建模軟件,繪制類圖軟件StarUML,microsoftWord2003等等。游戲?qū)崿F(xiàn)過程3.1游戲玩法設計玩家進入游戲場景,玩家通過點擊進入游戲,進入游戲界面后。我們會看到一個機器人。使用wasd鍵來控制機器人的行動方向。在界面的上方我們可以看到機器人的生命值。下面有可以使用的道具。明白以后你就可以開始我的探險游戲。在行走的過程中機器人會和山體樹木發(fā)生碰撞,機器人的運動狀態(tài)也會發(fā)生改變。該探險類游戲為單人游戲。該探險游戲的操作方式比較單一,主要是控制游戲角色的行走方向以及向敵人進行攻擊。方向鍵盤包括上下左右,分別用于控制機器人的前進和后退,左右轉(zhuǎn)角操作。而ctrl鍵用于攻擊敵人。3.2游戲內(nèi)容設計3.2.1關于劇情進入游戲后,玩家進入一個森林的游戲場景,玩家可以在道路上移動,在行走的過程中你可能會遇到一些物品,可以拾取到自己的背囊。還會遇到一個會攻擊機器人的小兔子。在玩家戰(zhàn)勝敵人后會有獎勵。3.2.2關于角色該游戲主要包括:玩家和兔子。玩家控制機器人向上下左右四個方向移動,并對兔子進行攻擊。兔子在遇到機器人的時候也會對玩家進行攻擊。3.2.3關于場景在unity中使用地形和模型的組合來雕琢游戲世界的空間,首先定制地形,在unity中可以使用高度圖來創(chuàng)建高度,使用筆刷來繪制高度,繪制貼圖等,并添加光照、陰影和天空盒和基于距離的無話效果,還有在地形上加入了水體。3.3游戲界面設計3.3.1游戲界面的框架設計游戲框架設計必須符合游戲的玩法和所使用的工具,不同于大型的MMOGame,該游戲沒有復雜的游戲系統(tǒng),更加側(cè)重游戲可玩性的設計,并且由于使用Unity3D引擎,省去很多底層模版的設計,其中核心的木板為:圖形渲染,物理仿真,網(wǎng)絡聯(lián)機。游戲系統(tǒng)的框架結(jié)構(gòu)圖如下:圖1游戲系統(tǒng)的框架結(jié)構(gòu)圖3.3.2界面設計本游戲作為3D游戲,3D游戲界面中主要實現(xiàn)游戲中場景和各個部件的繪制和控制,包括地面,天空,山體、樹木等。各種游戲模型及界面如下所示:圖2機器人角色模型圖3敵人角色模型圖4樹角色模型圖5設置觸發(fā)器圖6設置著色器圖7游戲菜單界面圖8積分榜界面

圖9游戲主界面3.4關卡設計3.4.1關卡及關卡中游戲元素該機器人探險游戲設有一個關卡,關卡由地形,天空盒,光照和陰影,山體,道路,天空,水體等元素構(gòu)成。地形:Unity3D中的地形模塊不但可以導入高度圖,還可以用筆刷為繪制地形紋理,樹木,草,大大減少了開發(fā)人員的工作量。天空盒:在Unity中,天空盒是一個特殊的虛擬盒子,它包裹在場景周圍;,在渲染設置中衛(wèi)整個場景一次性指定一個天空盒。光照和陰影:場景以光源的位置為視點被渲染,每個渲染圖像的像素的深度值被記錄在一個“深度紋理”中,被稱為陰影貼圖。3.4.2操作設計關卡的操作是通過鍵盤實現(xiàn)坦克的運動和攻擊。3.4.3運行時間每關運行時間是由開始游戲為起點玩家的失敗或者勝利最為結(jié)束點。3.4.4關卡設計流程確定關卡的元素確定關卡的元素關卡的元素的位置安排設計關卡元素的繪制關卡環(huán)境的美化圖10游戲關卡流程3.5游戲基本架構(gòu)和主要類設計3.5.1游戲的基本架構(gòu)(1)游戲的類框架圖11游戲的類框架圖(2)游戲界面的基本跳轉(zhuǎn)圖12游戲界面跳轉(zhuǎn)圖3.5.2主要類的設計游戲中開發(fā)的類比較多,為了讓讀者能夠更好的理解各個類的在游戲中所扮演的角色,本節(jié)將按照前面的框架分類對各個類的功能進行簡要介紹。(1)公共類MonoBehaviour類:每當想要在Unity中創(chuàng)建一個新的JavaScript腳本時,會自動從該類繼承,是的腳本可以訪問所有該類的內(nèi)置函數(shù)以及繼承而來的成員,它控制了和碰撞檢測、鼠標事件、攝像機事件、組件獲取以及比較相關的絕大部分函數(shù)。Animation類:該類負責對動畫剪輯進行播放、組合、和混合的所有功能。(2)游戲相關腳本代碼Widget_Cntroller.js:用于處理部件的運動和玩家的輸入Widget_Status.js:用于處理widget的狀態(tài)。Widget_Camera.js:用于控制攝像頭和使它順利地跟隨部件。Widget_Inventory.js:這里包括所有部件的收集的項目更新。Widget_AttackController.js:處理玩家的攻擊輸入和對目標敵人的傷害。Widget_Animation.js:Widget的動畫狀態(tài)管理器。WaypointBehavior.js:處理腳本在所有的waypointStoreFront.js:在waypoint處理采購變化PickupItems.js:處理所有widget可以拿起的部件GUI_WaypointStore.js:用于交易存儲接口處理GUI_MainMenu.js:為場景增加背景和主要的導航按鈕GUI_HUD.js:顯示pertinant信息窗口,他的項目,和任何現(xiàn)有的敵人。GUI_CustomControls.js:為在別處使用gui_customcontrols包含自定義復合控件類。Enemy_RespawnPoint.js:附加到場景中去作為敵人的重生點。當玩家走到指定的區(qū)域,一個新的敵人將重生。EBunny_Status.js:小兔子敵人的信息狀態(tài)控制。EBunny_AIController.js:用于處理電子兔子的AI和動畫。DamageTrigger.js:一個簡單的,可應用于任何類型的對象變量的損傷觸發(fā)。用于檢查損傷量的變化。Checkpoint.js:靜態(tài)聲明變量。3.6數(shù)據(jù)結(jié)構(gòu)與算法設計3.6.1數(shù)據(jù)結(jié)構(gòu)鏈表,哈希表是常用的數(shù)據(jù)結(jié)構(gòu),在該游戲中未用到相關的數(shù)據(jù)結(jié)構(gòu)。3.6.2算法設計(1)算法一:判斷玩家是否在攻擊范圍內(nèi)首先設置小兔子的攻擊半徑,當小兔子查看到自己離玩家的目標距離細雨它的攻擊半徑時,小兔子就開始攻擊。distanceToPlayer=transform.position-target.position;If(distanceToPlayer.magnitude<attackDistance)Return;Yield;(2)算法二:判斷玩家和小兔子的相對角度,使他面向玩家并向玩家移動。使用簡單的三角函數(shù)恒等式,我們就可以找到對應的角度,在FacePlayer()函數(shù)中加入如下代碼:varrelativeLocation=transform.InverseTransformPoint(targetLocation);Varangle=Mathf.Atan2(relativeLocation.x,relativeLocation.z)*Mathf.Rad2Deg;技術說明4.13D渲染絕大多數(shù)3D圖形庫實現(xiàn)都有相似操作順序,一系列相關的處理階段叫做3D圖形的渲染管線,基于頂點的操作與基本裝配:這個過程包括本地空間一世界空間一視圖空間一背面揀選,主要是根據(jù)編程人員設置的攝像機位置、視錐屬性和頂點索引對頂點數(shù)據(jù)進行一系列的數(shù)學運算,使3D圖形的形狀及位置得以正確顯示。像素操作:該過程主要根據(jù)編程人員傳入顯卡的紋理及頂點的紋理坐標以及光照信息進行顏色計算、混合,并對線、面采用線性插值、二次線性插值等算法最終進行出像素的顏色。這個過程的計算一般由顯卡固定管線的計算公式完成,如想得到更真實、更多樣的效果,可采用可編程管線技術實現(xiàn)。4.2動畫制作Unity中的動畫是由關鍵幀控制的。他們定義了動畫曲線。關鍵幀基本上保存了一個給定對象在某個特定時刻的狀態(tài)的快照,曲線定義為鏈接兩個或多個關鍵幀,以便對給定對象的完整運動路徑進行插值,一個對象的每個部分或者是組件都可以為任意給定的動畫剪輯包含自己的關鍵幀和曲線。4.3數(shù)據(jù)存儲文件存儲。4.4游戲特效在游戲中,游戲特效用于制作火花效果,很引人注目。游戲特效使游戲畫面更加充滿藝術的真實感,使玩家得到實時的沉浸感,更酣暢淋漓地體驗游戲的樂趣。在實時環(huán)境下有許多有趣并具有創(chuàng)造性的方法來實現(xiàn)游戲的特效,。下面主要介紹粒子系統(tǒng)。4.5粒子系統(tǒng)粒子系統(tǒng)即一組從特定物體或者位置發(fā)射出小的顆粒,游戲中這些小的粒子通常用的是小的二位圖形和點圖形,這些圖形都帶有小的紋理和Alpha通道,另外粒子具有生命周期、速度等屬性,并受重力等影響。粒子系統(tǒng)的應用是最為廣泛的,游戲中常常用來表現(xiàn)煙花、炮火、噴泉等等。游戲中為widget的攻擊設置了火花的效果。4.6碰撞檢測的實現(xiàn)在Unity3D中,能檢測碰撞發(fā)生的方式有兩種,一種是利用碰撞器,另一種則是利用觸發(fā)器。碰撞器的基本概念:(1)碰撞器是一群組件,它包含了很多種類,比如:BoxCollider,CapsuleCollider等,這些碰撞器應用的場合不同,但都必須加到GameObjecet身上。(2)所謂觸發(fā)器,只需要在檢視面板中的碰撞器組件中勾選IsTrigger屬性選擇框。

(3)在Unity3d中,主要有以下接口函數(shù)來處理這兩種碰撞檢測:觸發(fā)信息檢測,碰撞信息檢測。在該游戲中,我們創(chuàng)建一個齒輪這個預制模型,在project是視圖中選中它,并選擇Component→Physics→SphereCollider,為這個物品賦予一個新的Sphere碰撞體。在SphereCollider組建的Radius設置上面,單機IsTrigger框把它設置為Ture。這樣這個碰撞體現(xiàn)在的行為就和一個觸發(fā)器形體一樣。兩個GameObject發(fā)生碰撞,要想檢測到觸發(fā)信息,最少要有一個碰撞器并且勾選了IsTrigger復選框,另一個最少要有一個碰撞器組件。4.7游戲AIAI的全稱是ArtificialIntelligence(人工智能),AI是計算機學科的一個分支,它主要模擬人的思維過程,使計算機可以像人一樣行動和思考。AI在游戲中就是所編寫的代碼,如在給定的情形下,當游戲有多種選擇時,計算機控制的角色采取的是看起來比較聰明的決策,產(chǎn)生與之相關的有效和有用的行為。在游戲中,AI一般用在以下幾方面:游戲中智能體的設計(當游戲世界環(huán)境變化時,該智能體能夠感知環(huán)境并自動做出相應的動作);游戲世界中的尋路或者導航;其他AI技術如模糊邏輯的運用。游戲AI技術通常可以分為兩種,定性和非定性。定性AI適用于環(huán)境完全確定的情況,但現(xiàn)在這樣的環(huán)境其實是非常少的。非定性AI則可以適用于一些不確定的環(huán)境,但相對應的,其做出來的決策可能并不是最優(yōu)的。在以前,游戲中最廣泛使用的AI技術就是作弊,例如在戰(zhàn)爭模擬游戲中,由計算機控制的玩家,可以得知對手的所有信息,這樣根本就不需要偵察兵去收集這類情報。可是這樣會造成游戲中很多的不公平,而導致可玩性的下降?,F(xiàn)有的AI技術,以及某些人工生命技術,種類繁多,這里不再一一羅列。在機器人探險游戲中,我們實現(xiàn)小兔子自由的四處游蕩,直到它看到一個玩家并且上去追捕它。小兔子在設定的區(qū)域范圍內(nèi)轉(zhuǎn)向并向目標移動,在與目標發(fā)生碰撞就開始攻擊,當移動到范圍外,繼續(xù)游蕩,如果被打敗,丟下隨機小物品并且消失。AI在游戲中就是所編寫的代碼,如在給定的情形下,當游戲有多種選擇時,計算機控制的角色采取的是看起來比較聰明的決策,產(chǎn)生與之相關的有效和有用的行為。測試用例設計5.1測試用例編寫目的軟件測試就是利用測試工具按照測試方案和流程對產(chǎn)品進行功能和性能測試,甚至根據(jù)需要編寫不同的測試工具,設計和維護測試系統(tǒng),對測試方案可能出現(xiàn)的問題進行分析和評估。軟件測試就是在軟件交付用戶使用或投入運行前,對軟件需求規(guī)格說明、設計規(guī)格說明和編碼的最終復審,是軟件質(zhì)量保證的關鍵步驟。軟件測試是為了發(fā)現(xiàn)錯誤而執(zhí)行程序的過程。測試的最終目的是為了避免錯誤的發(fā)生,確保應用程序能夠正常高效的運行。好的測試用例在于發(fā)現(xiàn)至今未發(fā)現(xiàn)的錯誤,而成功的測試是發(fā)現(xiàn)了至今未發(fā)現(xiàn)的錯誤的測試。好的測試工程師應該做到不僅發(fā)現(xiàn)問題,還能夠幫助開發(fā)人員分析問題。該說明書通過一系列測試用例,達到測試游戲運行是否能夠達到預想狀態(tài)。5.2測試用例5.2.1被測試對象的介紹被測試的對象為Unity3d機器人探險游戲,該端游戲是3D的,基于unity,探險類游戲。5.2.2測試范圍與目的表3游戲測試范圍測試范圍測試目的界面測試檢測界面是否正常運行碰撞檢測檢測機器人、小兔子之間的碰撞檢測機器人檢測檢測機器人的移動,攻擊AI檢測檢測初步具有AI的物體是否能夠真的實現(xiàn)人工智能5.2.3測試環(huán)境與測試輔助工具的描述測試的環(huán)境是:Unity引擎。測試的輔助工具是:Window+Monodevelop。5.2.4功能測試用例功能測試就是檢測游戲的所需功能能否正常執(zhí)行,如下表所示:表4功能測試用例功能描述菜單界面測試用例目的菜單各按鈕是否能正確實現(xiàn)其功能前提條件程序運行正確輸入/動作期望的輸出/相應實際情況按下開始游戲按鈕進入游戲界面進入了游戲界面按下物品按鈕生命值增加玩家的生命值增加了功能描述游戲勝利檢測用例目的玩家勝利后是否可以獲得物品獎勵前提條件游戲勝利輸入/動作期望的輸出/相應實際情況按下開始游戲按鈕進入游戲進入游戲功能描述機器人與小兔子的碰撞檢測用例目的檢測機器人與小兔子能夠碰撞前提條件游戲正常運行,已進入游戲界面輸入/動作期望的輸出/相應實際情況攻擊小兔子玩家對小兔子進行強電流攻擊玩家對小兔子進行強電流攻擊功能描述玩家對小兔子的攻擊檢測用例目的檢測玩家是否能對小兔子進行攻擊前提條件游戲正常運行,已進入游戲界面輸入/動作期望的輸出/相應實際情況拾取物品將物品收入背囊,物品數(shù)增加將物品收入背囊,物品數(shù)增加功能描述背囊管理檢測用例目的檢測是機器人否可以拾取物品前提條件游戲正常運行,已進入游戲界面輸入/動作期望的輸出/相應實際情況小兔子攻擊玩家玩家的生命值減少玩家的生命值減少了功能描述小兔子對玩家的攻擊檢測用例目的檢測小兔子能否對玩家發(fā)出攻擊前提條件游戲正常運行,已進入游戲界面輸入/動作期望的輸出/相應實際情況點擊背囊按鈕玩家的生命值增加玩家的生命值增加了功能描述背囊管理檢測用例目的檢測背囊按鈕能否增加玩家生命值前提條件游戲正常運行,已進入游戲界面輸入/動作期望的輸出/相應實際情況通過方向鍵盤,使機器人前進的方式靠近小兔子機器人與小兔子發(fā)生碰撞,停止前進機器人與小兔子發(fā)生碰撞,停止前進功能描述機器人與小兔子的碰撞檢測用例目的檢測機器人能否與小兔子發(fā)生碰撞前提條件游戲正常運行,已進入游戲界面輸入/動作期望的輸出/相應實際情況通過方向鍵盤,使機器人進入水體電路短路機器人死亡電路短路機器人死亡功能描述機器人的死亡檢測用例目的檢測機器人遇到水體時是否死亡前提條件游戲正常運行,已進入游戲界面輸入/動作期望的輸出/相應實際情況小兔子死亡丟下獎勵物品并消失丟下獎勵物品并消失功能描述玩家獎勵檢測用例目的檢測小兔子死亡后是否能丟下獎勵物品前提條件游戲正常運行,已進入游戲界面5.3測試總結(jié)和改進建議在這次測試過程中發(fā)現(xiàn)了很多問問題,并及時的得到了解決了,使得游戲很多細節(jié)方面得到了改善。但是測試量還是有點大,很多不必要測試的數(shù)據(jù)被測試,走了彎路,以后可以更科學規(guī)劃測試計劃。總結(jié)本次工程實訓的內(nèi)容為基于Unity的3D機器人探險游戲。在本次實訓之前,由于自己對Unity掌握的并不是很好,所以在實訓開始的第一周,將主要的精力放在了對Unity基礎操作和基本代碼抒寫的學習上,以及完成了探險游戲的策劃。實訓第二周,完成的任務主要是觸發(fā)器和著色器的使用及相關代碼的抒寫。實訓第三周運用Apache搭建服務器,完成了積分榜的界面設計和數(shù)據(jù)傳輸。實訓第四周主要完成最終合成和游戲測試。在實訓的中期,當游戲開發(fā)小組在班上展示設計制作的作品時,說實話自己感受到了壓力,因為他們做的比自己的好很多。但動力也是在壓力下產(chǎn)生的,因此在實訓后期,我加快了開發(fā)步伐,最終較好的完成了本次實訓的內(nèi)容。最終較好的完成了3D機器人探險游戲。最后感謝老師在工程實訓中的耐心指導以及班上同學的幫助與支持,我們相信,下一次再有機會進行Unity的3D游戲設計時我會做的更好。參考文獻[1]吳亞峰.Unity43D開發(fā)實戰(zhàn)詳解.北京:人民郵電出版社,2012.[2]米歇爾.梅納徳著,Unity游戲開發(fā)實戰(zhàn).北京:機械工業(yè)出版社,2012.[3]李振,蘇南.Java5游戲開發(fā).北京:機械工業(yè)出版社,2007.[4]敖富江.3D游戲編程入門經(jīng)典.北京:清華大學出版社,2006.[5]白潔,羅穎民.游戲開發(fā)與制作.北京:清華大學出版社,2007.[6]汪永松.Android平臺開發(fā)之旅.北京:機械工業(yè)出版社,2012.附錄游戲核心代碼(1)機器人的角色控制核心代碼 //MovethecontrollerduringthefixedframeupdatesfunctionFixedUpdate(){ //checktomakesurethecharacteriscontrollableandnotdead if(!isControllable) Input.ResetInputAxes(); else{ if(grounded){ //Sincewe'retouchingsomethingsolid,liketheground,allowmovement //CalculatemovementdirectlyfromInputAxes moveDirection=newVector3(Input.GetAxis("Horizontal"),0,Input.GetAxis("Vertical")); moveDirection=transform.TransformDirection(moveDirection); moveDirection*=rollSpeed; //Findrotationbaseduponaxesifneedtoturn moveHorz=Input.GetAxis("Horizontal"); if(moveHorz>0)//rightturn rotateDirection=newVector3(0,1,0); elseif(moveHorz<0)//leftturn rotateDirection=newVector3(0,-1,0); else//notturning rotateDirection=newVector3(0,0,0); //JumpControls if(Input.GetButton("Jump")){ moveDirection.y=jumpSpeed; } //ApplyanyBoostedSpeed if(Input.GetButton("Boost")){ if(widgetStatus){ if(widgetStatus.energy>0) { moveDirection*=fastRollSpeed; widgetStatus.energy-=widgetStatus.widgetBoostUsage*Time.deltaTime; isBoosting=true; } } } //Duckthecontroller if(Input.GetButton("Duck")){ controller.height=duckHeight; controller.center.y=controller.height/2+.25; moveDirection*=duckSpeed; isDucking=true; } if(Input.GetButtonUp("Duck")){ controller.height=normalHeight;//resetforafterducks controller.center.y=controller.height/2;//recenterforafterducks isDucking=false; } if(Input.GetButtonUp("Boost")){ isBoosting=false; } } //ApplygravitytoendJump,enablefalling,andmakesurehe'stouchingtheground moveDirection.y-=gravity*Time.deltaTime; //Moveandrotatethecontroller varflags=controller.Move(moveDirection*Time.deltaTime); controller.transform.Rotate(rotateDirection*Time.deltaTime,rotateSpeed); grounded=((flags&CollisionFlags.CollidedBelow)!=0); } }functionIsMoving(){ returnmoveDirection.magnitude>0.5;}functionIsDucking(){ returnisDucking;}functionIsBoosting(){ returnisBoosting;}functionIsGrounded(){ returngrounded;}(2)機器人的狀態(tài)處理核心代碼functionApplyDamage(damage:float){ health-=damage; //playhitsoundifitexists if(hitSound) { audio.clip=hitSound; audio.Play(); } //checkhealthandcallDieifneedto if(health<=0){ health=0;//forGUI Die(); }}functionAddHealth(boost:float){ //addhealthandsettominof(currenthealth+boost)orhealthmax health+=boost; if(health>=maxHealth){ health=maxHealth; } print("addedhealth:"+health);}functionAddEnergy(boost:float){ //addenergyandsettonimof(currenten+boost)orenmax energy+=boost; if(energy>=maxEnergy){ energy=maxEnergy; } print("addedenergy:"+energy);}functionDie(){ //playdeathsoundifitexists if(deathSound) { audio.clip=deathSound; audio.Play(); } print("dead!"); playerController.isControllable=false; animationState=GetComponent(Widget_Animation); animationState.PlayDie(); yieldWaitForSeconds(animation["Die"].length-0.2); HideCharacter(); yieldWaitForSeconds(1); //restartplayeratlastrespawncheckpointandgivemaxlife if(CheckPoint.isActivePt){ controller.transform.position=CheckPoint.isActivePt.transform.position; controller.transform.position.y+=0.5;//sonottogetstuckintheplatformitself } ShowCharacter(); health=maxHealth;}functionHideCharacter(){ GameObject.Find("Body").GetComponent(SkinnedMeshRenderer).enabled=false; GameObject.Find("Wheels").GetComponent(SkinnedMeshRenderer).enabled=false; playerController.isControllable=false; }functionShowCharacter(){ GameObject.Find("Body").GetComponent(SkinnedMeshRenderer).enabled=true; GameObject.Find("Wheels").GetComponent(SkinnedMeshRenderer).enabled=true; playerController.isControllable=true; }(3)AI控制核心代碼privatevarisAttacking=false;privatevarlastAttackTime=0.0;privatevarnextPauseTime=0.0;privatevardistanceToPlayer;privatevartimeToNewDirection=0.0;vartarget:Transform;//CachethecontrollerprivatevarcharacterController:CharacterController;characterController=GetComponent(CharacterController);//functionStart(){ if(!target) target=GameObject.FindWithTag("Player").transform; //Setupanimations animation.wrapMode=WrapMode.Loop; animation["EBunny_Death"].wrapMode=WrapMode.Once; animation["EBunny_Attack"].layer=1; animation["EBunny_Hit"].layer=3; animation["EBunny_Death"].layer=5; //Ratherthanplacingthisinanupdatefunction,wecanstarttheAI'sbehaviornowand //usecoroutinestohandlethechanges yieldWaitForSeconds(idleTime); while(true) { //Idlearoundandwaitfortheplayer yieldIdle(); //Playerhasbeenlocated,preparefortheattack. yieldAttack(); }}functionIdle(){ //Walkaroundandpauseinrandomdirectionsunlesstheplayeriswithinrange while(true) { //Findanewdirectiontomove if(Time.time>timeToNewDirection) { yieldWaitForSeconds(idleTime); varRandomDirection=Random.value; if(Random.value>0.5) transform.Rotate(Vector3(0,5,0),rotateSpeed); else transform.Rotate(Vector3(0,-5,0),rotateSpeed); timeToNewDirection=Time.time+directionTraveltime; } varwalkForward=transform.TransformDirection(Vector3.forward); characterController.SimpleMove(walkForward*walkSpeed); distanceToPlayer=transform.position-target.position; //Wefoundtheplayer!Stopwastingtimeandgoafterhim if(distanceToPlayer.magnitude<attackDistance) return; yield; }}functionAttack(){ isAttacking=true; animation.Play("EBunny_Attack"); //Weneedtoturntofacetheplayernowthathe'sinrange. varangle=0.0; vartime=0.0; vardirection:Vector3; while(angle>viewAngle||time<attackTurnTime) { time+=Time.deltaTime; angle=Mathf.Abs(FacePlayer(target.position,attackRotateSpeed)); move=Mathf.Clamp01((90-angle)/90); //dependingontheangle,startmoving animation["EBunny_Attack"].weight=animation["EBunny_Attack"].speed=move; direction=transform.TransformDirection(Vector3.forward*attackSpeed*move); characterController.SimpleMove(direction); yield; } //attackifcanseeplayer varlostSight=false; while(!lostSight) { angle=FacePlayer(target.position,attackRotateSpeed); //ChecktoensurethatthetargetiswithintheBunny'seyesight if(Mathf.Abs(angle)>viewAngle) lostSight=true; //Ifbunnylosessiteoftheplayer,hejumpsoutofhere. if(lostSight) break; //Checktoseeifwe'recloseenoughtotheplayertobite'em. varlocation=transform.TransformPoint(attackPosition)-target.position; if(Time.time>lastAttackTime+1.0&&location.magnitude<attackRadius) { //dealdamage target.SendMessage("ApplyDamage",damage); lastAttackTime=Time.time; } if(location.magnitude>attackRadius) break; //Checktomakesureourcurrentdirectiondidn'tcollideuswithsomething if(characterController.velocity.magnitude<attackSpeed*0.3) break; //yieldforoneframe yield; } isAttacking=false;}functionFacePlayer(targetLocation:Vector3,rotateSpeed:float):float{ //Findtherelativeplaceintheworldwheretheplayerislocated varrelativeLocation=transform.InverseTransformPoint(targetLocation); varangle=Mathf.Atan2(relativeLocation.x,relativeLocation.z)*Mathf.Rad2Deg; //Clampitwiththemaxrotationspeedsohedoesn'tmovetoofast varmaxRotation=rotateSpeed*Time.deltaTime; varclampedAngle=Mathf.Clamp(angle,-maxRotation,maxRotation); //Rotate transform.Rotate(0,clampedAngle,0); returnangle;}(4)拾取物品和背囊管理核心代碼PickupItems.js://PickupItems:handlesanyitemslyingaroundtheworldthatWidgetcanpickupvaritemType:InventoryItem;varitemAmount=1;varsparkleEmitter:ParticleEmitter;privatevarpickedUp=false;//WhenWidgetfindsanitemonthefieldfunctionOnTriggerEnter(collider:Collider){ //makesurethatthisisaplayerhittingtheitemandnotanenemy varplayerStatus:Widget_Status=collider.GetComponent(Widget_Status); if(playerStatus==null)return; //stopitfrombeingpickeduptwicebyaccident if(pickedUp)return; //Ifeverything'sgood,putitinWidget'sInventory varwidgetInventory=collider.GetComponent(Widget_Inventory); widgetInventory.GetItem(itemType,itemAmount); pickedUp=true; //playanysoundforpickingitup //stopanyFXwhenpickingitup sparkleEmitter.emit=false; //Getridofitnowthatit'sintheinventory Destroy(gameObject);}//MakesurethepickupissetupproperlywithacolliderfunctionReset(){ if(collider==null) { gameObject.AddComponent(SphereCollider); } collider.isTrigger=true; sparkleEmitter.emit=true;}Widget_Invebtory.js:enumInventoryItem{ DEBUG_ITEM, SCREW, NUT, BOSS_TRAY, BOSS_PLOWBLADE, BOSS_WINDBLADE, ENERGYPACK, REPAIRKIT, COUNT_NUM_ITEMS}//We'lluseastaticallytypedBuiltInarrayratherthanaJavascriptarrayhere.varwidgetInventory:int[];varplayerStatus:Widget_Status;playerStatus=GetComponent(Widget_Status);//ItemPropertiesprivatevarrepairKitHealAmt=5.0;privatevarenergyPackHealAmt=5.0;//InitilizeWidget'sstartingInventoryfunctionAwake(){ //widgetInventory=newint[InventoryItem.COUNT_NUM_ITEMS]; widgetInventory=newint[8]; for(variteminwidgetInventory){ widgetInventory[item]=0; } //GiveWidgetsomestartingitems widgetInventory[InventoryItem.ENERGYPACK]=1; widgetInventory[InventoryItem.REPAIRKIT]=2;}//InventoryManagementFunctionsfunctionGetItem(item:InventoryItem,amount:int){ widgetInventory[item]+=amount;}functionUseItem(item:InventoryItem,amount:int){ if(widgetInventory[item]<=0)return; widgetInventory[item]-=amount; switch(item){ caseInventoryItem.ENERGYPACK: playerStatus.AddEnergy(energyPackHealAmt); break; caseInventoryItem.REPAIRKIT: playerStatus.AddHealth(repairKitHealAmt); break; }}functionCompareItemCount(compItem:InventoryItem,compNumber:int){ returnwidgetInventory[compItem]>=compNumber;}functionGetItemCount(compItem:InventoryItem){ returnwidgetInventory[compItem];}(5)碰撞檢測核心代碼DamageTrigger.js://DamageTrigger.js:Asimple,variabledamagetriggerwhichcanbeappliedtoanykindofobject.//ChangethedamageamountintheInspector.vardamage:float=20.0;varplayerStatus:Widget_Status;func

溫馨提示

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

評論

0/150

提交評論