版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
目錄TOC\o"1-4"\h\z\u摘要 [26]。游戲中的角色在場景中出現(xiàn)使用了預(yù)制體加載。首先將人物資源拖拽到項(xiàng)目中形成它的預(yù)制體,預(yù)制體顯示為藍(lán)色。如圖3.7所示。圖3.7預(yù)制體示例點(diǎn)擊預(yù)制體會進(jìn)行對預(yù)制體的編輯,這樣通過腳本調(diào)用到的預(yù)制體模型進(jìn)行克隆,克隆后的物體都會根據(jù)默認(rèn)設(shè)置好的屬性出現(xiàn),不用重復(fù)編輯腳本。3.6攝像機(jī)控制攝像機(jī)是每次開啟新工程默認(rèn)自帶的組件,它用來向玩家獲取和顯示世界到Game面板中,相當(dāng)于玩家看向游戲世界的“眼睛”,不光可以用作視角,還可以制作小地圖等功能。在場景中可以放置的攝像機(jī)數(shù)目不等,在這個游戲中我放置了一個攝像機(jī)。攝像機(jī)含有不同的組件,有和其他所有組件同樣的Transform變換,還有它獨(dú)有的Camera組件、音頻監(jiān)視器AudioListener。Camera是用來捕獲和顯示世界,AudioListener用來接收場景中的聲音,并在游戲中通過計(jì)算機(jī)的揚(yáng)聲器進(jìn)行播放。同時攝像機(jī)的CullingMask剔除遮擋功能可以通過勾選游戲場景中設(shè)定好的層,控制游戲進(jìn)行時玩家哪些游戲?qū)ο笫强吹玫降哪男┛床坏?,從而提高游戲界面的整潔度。為了在游戲中產(chǎn)生第三人稱視角,在游戲中將攝像機(jī)放在Hierarchy中角色下取名為PlayerCamera,攝像機(jī)跟隨角色移動,就可以實(shí)時捕捉到主人物和周圍物體的畫面。在Scene中進(jìn)行調(diào)節(jié)攝像機(jī)的位置,使攝像機(jī)固定在主角的后方位置。而后在參數(shù)面板對攝像機(jī)的各項(xiàng)參數(shù)進(jìn)行調(diào)節(jié),同時之后的腳本中可以控制相應(yīng)參數(shù)。調(diào)節(jié)相應(yīng)的初試參數(shù)如圖3.8所示。圖3.8攝像機(jī)的設(shè)置參數(shù)攝像機(jī)設(shè)置的相關(guān)代碼如下。voidStart(){Cursor.visible=false;}voidLateUpdate(){MouseControl();}voidMouseControl(){floatmouser_Y=Input.GetAxis("MouseY");transform.RotateAround(Player.transform.position,transform.right,Mathf.Lerp(mouser_Y,mouser_Y*5f,0));if(Input.GetKey(KeyCode.LeftAlt)){Cursor.visible=true;Cursor.lockState=CursorLockMode.Confined;}elseif(Input.GetKeyUp(KeyCode.LeftAlt))Cursor.visible=false;}3.7本章小結(jié)本章是整篇論文的重要部分,主要內(nèi)容是游戲制作中的各個主要模塊,以及其中用到的Unity相關(guān)技術(shù)的使用和這些技術(shù)的簡單說明,這些系統(tǒng)設(shè)計(jì)為之后的一系列操作做了鋪墊。同時附著上一些相關(guān)的主要代碼,使文章表達(dá)更加直觀。4.系統(tǒng)實(shí)現(xiàn) 4.1腳本實(shí)現(xiàn)為了在游戲制作過程中更加便捷的觀察各種參數(shù)的變化并加以改動,游戲中使用到了腳本拓展,可以將原本的編程語言在Hierarchy面板中用中文表示出來,很方便理解。首先在腳本文件夾中創(chuàng)建專門用來負(fù)責(zé)腳本二次編輯的文件夾Editor。這里是用到了下載好的用作代碼重寫的插件,通過調(diào)用插件中的Api進(jìn)行代碼重寫的實(shí)現(xiàn),具體調(diào)用并重寫的代碼一部分如下:AlignTextCue("設(shè)置怪物");//monsterPatrol_Edior.targetCamera=(Camera)EditorGUILayout.ObjectField("玩家攝像機(jī)",monsterPatrol_Edior.targetCamera,typeof(Camera),true);monsterPatrol_Edior.monsterObject=(GameObject)EditorGUILayout.ObjectField("怪物指定",monsterPatrol_Edior.monsterObject,typeof(GameObject),true);monsterPatrol_Edior.monsterName=(string)EditorGUILayout.TextField("怪物預(yù)設(shè)名字",monsterPatrol_Edior.monsterName);monsterPatrol_Edior.monsterLevel=(int)EditorGUILayout.IntField("怪物預(yù)設(shè)等級",monsterPatrol_Edior.monsterLevel);monsterPatrol_Edior.monsterHP=(float)EditorGUILayout.FloatField("怪物預(yù)設(shè)血量",monsterPatrol_Edior.monsterHP);//dataControl._camera=(Camera)EditorGUILayout.ObjectField("攝像機(jī)指定",dataControl._camera,typeof(Camera),true);dataControl._DeffaultPlyerHp=(float)EditorGUILayout.FloatField("玩家預(yù)設(shè)血量",dataControl._DeffaultPlyerHp);dataControl._DeffaultPlyerAttck=(int)EditorGUILayout.IntField("玩家預(yù)設(shè)攻擊",dataControl._DeffaultPlyerAttck);foldout=EditorGUILayout.Foldout(foldout,"戰(zhàn)斗檢測參數(shù)",false);if(foldout){monsterPatrol_Edior.layervalue=EditorGUILayout.LayerField("怪物可感知層",monsterPatrol_Edior.layervalue);monsterPatrol_Edior.dangerNameColor=EditorGUILayout.ColorField("怪物戰(zhàn)斗顏色",monsterPatrol_Edior.dangerNameColor);stance=EditorGUILayout.Slider("怪物追擊距離",monsterPatrol_Edior.followDistance,0,10);}通過該腳本將原本復(fù)雜的代碼在Hierarchy中小怪獸掛載的腳本控制變成如圖4.1。這樣視覺上效果更加清晰,如果開發(fā)者在過后想要新添加小怪獸或者其他用戶想通過這個項(xiàng)目來對游戲進(jìn)行一些修改就會十分方便如圖可以通過拖拽、掛載的方式加載預(yù)制體新建小怪物,設(shè)置空物體為它的路線,然后直接通過腳本二次編輯后的界面進(jìn)行戰(zhàn)斗顏色、追擊等等相關(guān)屬性的調(diào)節(jié)。這里以小怪獸腳本的掛載為例,主角的腳本二次編輯效果同理。圖4.1腳本拓展的效果4.2場景實(shí)現(xiàn) 游戲的場景主要是Unity官網(wǎng)的素材,配有設(shè)置好的Shader,項(xiàng)目中對場景的控制主要是對場景中的細(xì)節(jié)進(jìn)行一些編輯,調(diào)節(jié)各個游戲?qū)ο蟀ㄌ炜?、樹木的顏色等,調(diào)節(jié)模塊如圖4.2。圖4.2環(huán)境調(diào)節(jié)面板4.3NPC對話實(shí)現(xiàn)進(jìn)入游戲開始出現(xiàn)對話框,在腳本Frame中設(shè)置變量buttonValue記錄用戶按下鼠標(biāo)左鍵的次數(shù),通過buttonValue的值依次顯示對話框中的每一句內(nèi)容。效果如圖4.3。圖4.3NPC對話實(shí)現(xiàn)主要代碼如下voidStart(){inset.DOFade(0,0);sq=DOTween.Sequence();GameDate.Game_data._IsMonUi=false;Skill.SetActive(false);}publicvoidButtoValue(){buttonValue++;if(_buttonValue==1){sq.Append(transform.GetComponent<Text>().DOText("",.1f));sq.Append(transform.GetComponent<Text>().DOText("伊撒爾鎮(zhèn)是一個和平寧靜的小鎮(zhèn),在它平和的外表下誕生了許多于這個世界披荊斬棘的勇士們。在這個冒險(xiǎn)世界中,任何堅(jiān)毅果敢的勇士多需要不斷地磨煉,從迎接他的第一次任務(wù)開始。",3));}4.4人物動作實(shí)現(xiàn)在Project面板中右鍵選擇,創(chuàng)建一個AnimatorController,將人物的多種模型包括動畫片段拖拽進(jìn)AnimatorController窗口中,可以在資源中分別點(diǎn)擊人物模型的動作文件預(yù)覽每一個不同的動作是什么。如圖是Animator動畫狀態(tài)機(jī),使用腳本控制一個角色的每一個動作是一個復(fù)雜的動作,通過動畫狀態(tài)機(jī)方便更加簡單的控制和序列化動畫。如圖4.4。圖4.4動畫狀態(tài)機(jī)動畫狀態(tài)機(jī)中的每一個箭頭都是一個變量,在腳本中是通過各種條件控制的bool值。在動作樹中對動作進(jìn)行拖拽,設(shè)置箭頭指向它們之間的關(guān)系。在代碼的控制下人物的動作之間進(jìn)行過渡。為了動畫的過渡更加平滑,游戲的動作實(shí)現(xiàn)添加了混合樹,在動作樹下雙擊動作的名稱進(jìn)入混合樹面板?;旌蠘渫ㄟ^腳本中的混合參數(shù)控制人物素材中的每一個動作對于最終效果的權(quán)重?;旌蠘淙鐖D4.5.圖4.5混合樹示例游戲中在Walk中設(shè)置了混合樹,因?yàn)橛螒蛑械暮芏鄤幼鞫际窃谛凶叩臓顟B(tài)中實(shí)現(xiàn)的,比如行走時右轉(zhuǎn)、行走時奔跑、行走時拔刀。在混合樹種通過x軸與y軸的變換來實(shí)現(xiàn)平滑的動畫效果。怪物的動作和主角的動作同理。4.5UI實(shí)現(xiàn)在項(xiàng)目中的Hierarchy面板中右鍵創(chuàng)建Canvas畫布,在2D下的UI面板就在這個畫布中顯示。找到相應(yīng)的UI素材存放在Hierarchy面板中的UI文件下,每一張圖片都是UI整體的一部分,通過代碼控制這些圖片的顯示??刂芔I的腳本主要由三個文件,在Project下Script文件夾中,分別是Frame、SimpleUI、ValueUI,分別控制UI文字對話框的顯示、菜單欄(包括重新開始游戲、繼續(xù)游戲、關(guān)閉游戲)以及任務(wù)框任務(wù)完成后的提示。這些UI與其他模塊也息息相關(guān)有相通的地方,比如任務(wù)面板中的怪物剩余的顯示,在怪物相關(guān)腳本中和控制怪物的變量聯(lián)系起來,互相配合完成任務(wù)中怪物剩余量的顯示。相關(guān)代碼如下。voidUpdate(){gameObject.GetComponent<Text>().text=GameDate.Game_data._Score.ToString();if(GameDate.Game_data._Score==5){renwu.text="任務(wù)完成,繼續(xù)漫游或者退出游戲";}}4.6戰(zhàn)斗碰撞監(jiān)測實(shí)現(xiàn)首先設(shè)置主角的碰撞體設(shè)置,在人物上添加剛體組件,設(shè)置質(zhì)量Mass為1;UseGravity處勾選,表示角色會受到重力的影響;IsKinematic處取消勾選,這個是采取動力學(xué)的選項(xiàng),如果勾選則角色不再受物理系統(tǒng)的影響;Drag阻力為0,空氣阻力是角色運(yùn)動時收到空氣阻力的大小,這個值越大角色運(yùn)動越慢;。小怪物的剛體組件Rigidbody屬性設(shè)置與主角的相同。小怪物和主角的碰撞體選擇都是CapsuleCollider膠囊碰撞體組件;Material是材質(zhì),這里沒有拖拽進(jìn)去其他材質(zhì),因?yàn)槿宋锬P褪穷A(yù)先編輯好的;Radius和Height屬性分別對碰撞體組建的半徑和高進(jìn)行設(shè)置,這里設(shè)置為0.2和1.41。小怪獸的設(shè)定和主角的碰撞體設(shè)定類似。設(shè)置好Unity面板中的這些參數(shù)后就可以用腳本來對這些參數(shù)進(jìn)行控制。privatevoidUpdate(){Debug.Log(PlyerDefault.PlyerHp);AddDanmeger();}publicvirtualvoidCombatDetection(){Debug.LogWarning(PlyerDefault.PlyerHp);}//檢測到兩個接觸到了就會造成傷害voidAddDanmeger(){Debug.Log(CollisionObject);if(CollisionObject==2&&AnimationKey.damage==true){GameDate.Game_data._isDamager=true;AnimationKey.damage=false;CollisionObject=0;}}4.7本章小結(jié)本章主要是系統(tǒng)的實(shí)現(xiàn),系統(tǒng)經(jīng)過一系列設(shè)計(jì)和編程之后指定的功能大多數(shù)處理完畢,然后進(jìn)行了腳本的二次編輯。到這里整個項(xiàng)目大致完成了,接下來還需要進(jìn)行游戲測試來完善它。5.系統(tǒng)測試5.1功能測試為了確保該項(xiàng)目的游戲質(zhì)量,在游戲制作后需要進(jìn)行整體的測試,主要就是找到游戲中存有的未發(fā)現(xiàn)的bug,這些bug有可能是程序本身邏輯錯誤造成的,也有可能是代碼細(xì)節(jié)上的小錯誤,還可能是版本問題和美術(shù)資源的問題造成的。修改這些游戲中可能出現(xiàn)的紕漏以及改進(jìn)游戲中的缺陷來提高游戲的整體質(zhì)量,使得游戲更加合理,從而有更為良好的游戲體驗(yàn)。由于在修改bug的過程中本身可能會造成新的bug出現(xiàn),所以需要不斷的進(jìn)行全面的測試。5.2人物動作測試游戲運(yùn)行中通過鼠標(biāo)和鍵盤的按鍵可以順暢的控制人物的各種動作,主角的行走、奔跑、奔跑時拔刀、跳躍等等動作都可以在相應(yīng)按鍵條件下順利執(zhí)行,這些動作在調(diào)整好的參數(shù)下互相之間切換順暢,沒有出現(xiàn)卡頓,突然變換動作這樣不自然的效果。人物攻擊的時候,人物施展動作動畫碰撞體檢測到小怪物,怪物隨之掉血。如圖5.1和5.2展示了其中兩個動作。圖5.1角色動作示例1揮刀圖5.2角色動作示例2左閃5.3戰(zhàn)斗系統(tǒng)測試5.4UI測試打開游戲后按下esc鍵開始游戲,開始游戲后游戲界面是黑色的,下方彈出對話框,鼠標(biāo)每點(diǎn)擊一下對話框中的內(nèi)容就會往下變換一次。主角聽到有人叫他后NPC的立繪會在對話框上方顯示,全部對話結(jié)束后立繪和對話框消失,切換到游戲畫面中,主角開始可以自由行動。如圖5.3。圖5.3UI效果示例1UI界面可以看到主角的剩余血量,血量條是紫色,右方的怪物面板還有右上角的設(shè)置主角向怪物區(qū)域行走后可以看到小怪物頭頂?shù)腢I,包含怪物本身的血量和等級。當(dāng)主角離小怪物比較遠(yuǎn)的時候小怪物頭頂?shù)腢I會變小,當(dāng)主句離小怪物較近的時候小怪物頭頂?shù)腢I會隨之變大,主人物和小怪物互相攻擊的時候,血量條會根據(jù)雙方的攻擊造成的傷害遞減,每打敗一個小怪物右方任務(wù)面板的當(dāng)前進(jìn)度就會產(chǎn)生變化[27]。點(diǎn)擊右上角的設(shè)置,進(jìn)入菜單欄的UI,可以看到三個按鈕。繼續(xù)游戲,雙擊繼續(xù)游戲回到剛才的狀態(tài)繼續(xù)運(yùn)行;重新開始,雙擊重新開始游戲會回到最開始的樣子;返回桌面,雙擊返回桌面游戲退出。如圖5.4,5.5。圖5.4UI效果示例2圖5.5UI效果示例35.5性能測試在游戲的運(yùn)行過程中曾經(jīng)多次出現(xiàn)過BUG,從一開始處理游戲模型時動作銜接不上導(dǎo)致玩家動作怪異,到過程中斜寫下的代碼沒有成功執(zhí)行效果,每添加一個新的功能都會存在新增BUG的可能。BUG的測試主要通過Debug來進(jìn)行調(diào)節(jié),還有在代碼的行前面添加斷點(diǎn),通過在Console上顯示的語句和斷點(diǎn)所在變量的數(shù)值變化考慮代碼的問題出現(xiàn)在哪里。經(jīng)過多次修改,通過多次運(yùn)行后檢查到游戲沒有出現(xiàn)功能上的bug,然后開始對游戲的性能進(jìn)行測試。對游戲性能的檢測可以通過drawcall來反應(yīng)。draw在Game面板下的Statue中顯示drawcall是由CPU發(fā)起由GPU接收的用于繪制渲染的次數(shù),它的數(shù)值越大性能占用就會越多。在代碼中可以通過控制drawcall的方式來優(yōu)化性能。比如說使用遮擋剔除,通過設(shè)置不同的層級控制不同的景色,在角色行走的過程中將不應(yīng)該看到的景象剔除掉。同時也可以觀察對性能的占用,打開左上角的Windows,觀察其中的Profiler,當(dāng)游戲運(yùn)行的時候可以通過Profiler來觀察屏幕后面發(fā)生了什么并且通過這些信息進(jìn)行跟蹤,查看造成性能問題的原因。比如說以CPU的占用為例。打開游戲,在游戲運(yùn)行的時候觀察Profiler里面CPU分析器的層次結(jié)構(gòu)圖,觀察當(dāng)前幀數(shù)哪一項(xiàng)CPU花費(fèi)時間是最多的。如圖可以看到在PlayerLoop下Camera.Render是最耗時的。這樣就可以明白性能是怎樣隨著時間共同變化的。在這里可以通過CPU一幀一幀的尋找單個最為耗時的函數(shù)。具體圖像如圖5.6。同理內(nèi)存的消耗也可以通過這種方式進(jìn)行觀察。圖5.6性能占用數(shù)值該游戲是屬于pc端的游戲,通過Profiler可以看出CPU耗時在每幀花費(fèi)20到80毫秒不等,游戲過程中運(yùn)行比較通順,沒有感到卡頓的地方。5.6本章小結(jié)本章的主要內(nèi)容是進(jìn)行游戲測試,包括對UI的測試、環(huán)境的測試和各個功能之間的測試。通過測試可以發(fā)現(xiàn)游戲中的不足。通過一次次的運(yùn)行調(diào)節(jié)在項(xiàng)目中發(fā)現(xiàn)問題并進(jìn)行改善,從而提高整個游戲的質(zhì)量。結(jié)論以上就是制作改項(xiàng)目游戲的步驟和一些分析。項(xiàng)目基本達(dá)到預(yù)期的效果,該游戲?qū)⑤p松的劇情融入到氛圍怡然的游戲場景中,角色在游戲場景中動作切換自然,游戲中一些系統(tǒng)功能的效果也達(dá)到了最初的要求。在游戲中用戶可以體會戰(zhàn)斗的樂趣,在精致的場景中漫游作為休閑。雖然完成了該游戲的設(shè)計(jì)和制作,仍然有一些不足的地方。比如C#腳本的語言和算法的編寫需要更加精進(jìn),代碼結(jié)構(gòu)需要更加規(guī)整有層次,劇情上有一定需要完善的地方,都有待后續(xù)不斷提高和加強(qiáng)。制作這個游戲,涉及到Unity很多基礎(chǔ)知識,比如編輯器界面中不同組件和窗口的使用、UI的設(shè)計(jì)、如何使用物理功能、調(diào)試優(yōu)化腳本,以及一些很方便的小功能如腳本拓展。借助Unity引擎開發(fā)的這款游戲,從最開始的游戲規(guī)則設(shè)計(jì)、場景的設(shè)計(jì)和調(diào)節(jié)、游戲人物的設(shè)計(jì)、到游戲中場景和游戲?qū)ο蠼换スδ艿膶?shí)現(xiàn),再到音樂的使用優(yōu)化和UI的設(shè)計(jì),整個游戲制作流程按照規(guī)范進(jìn)行開發(fā),并且它的測試達(dá)到了功能設(shè)計(jì)中的要求。用戶在使用Unity游戲引擎進(jìn)行游戲開發(fā)的過程中可以看到清晰的界面和相關(guān)說明,便于理解各種使用方法和函數(shù)、組件的功能,通過Unity設(shè)計(jì)出來的游戲在視覺效果上、游戲動作的變換形式和場景變換上都有非常棒的效果。并且能夠在很多平臺上進(jìn)行移植,具有很好的交互性,在使用中非常方便。致謝在綠島的四年光陰似水,滿眼繁華,轉(zhuǎn)眼間就到了分別的時候,離開時是剪不斷的牽念。每一個故事都會有結(jié)局,這四年,快樂也有,悲傷也罷,我總會記得在自己青春最美好的四年里,水上圖書館外寧靜的綠島湖,回宿舍的那一長串林蔭道,白卿宮外的梨花。會者定離,一期一祈,腦海里的目光所及,盡是你全部的美好。我記得我曾經(jīng)在夜晚的二期操場上和小伙伴奔跑,風(fēng)微涼,草坪上總會看到一些熟悉的面孔;我記得在機(jī)電學(xué)院齒輪狀的大樓里每天的上課下課,和室友同學(xué)走在長廊里的每一處,夏日里機(jī)電學(xué)院很悶熱,后來安裝了空調(diào),就成了很多人自習(xí)喜歡去的地方;我記得校園外的水果攤;記得食堂二樓活動室偶爾傳來的樂聲;記得校園內(nèi)的第一樹桃花開放后一直到秋天滿目楓葉紅,每天都會有不同種類的花在綻放;最重要的是,記得大學(xué)這些年陪伴過我的每一個人,感謝他們。相逢一面太匆匆,校里繁花幾度紅。終于到了這分別的時候,這篇論文也變成了我大學(xué)四年的最后一次作業(yè)。感謝這四年來遇見的每一個幫助過我的老師,每一個幫助我課業(yè)的同學(xué)。很遺憾這四年我沒有為自己付出的努力更多一些,但也慶幸于這四年來我為自己做出的改變。路漫漫其修遠(yuǎn)兮,在這里經(jīng)歷的每一段故事,遇見的每一個人都匯聚成我人生的一部分,陪著我向未來走下去。同時,要感謝這一年幫助我的論文指導(dǎo)老師高麗老師,用心指導(dǎo)我的論文在我有許多錯誤的時候打電話給我,以及我的實(shí)習(xí)指導(dǎo)老師聶菲老師在我實(shí)習(xí)過程中對我的幫助。還有我的系主任郭鳴宇老師和李朋老師以及班主任陳思老師和大學(xué)期間的每一個老師在我這四年以來對我的幫助。我的論文寫至這里,畫上一個句點(diǎn)。如今別離,且行且珍惜。參考文獻(xiàn)李詩瑤,司占軍,浦英.交互式虛擬場景在實(shí)驗(yàn)室安全教育中的應(yīng)用與研究[J].電腦知識與技術(shù),2020,16(04):215-217.楊曉虎,朱穎,朱珣.基于Unity3D游戲開發(fā)的批處理技術(shù)研究[J].科技創(chuàng)新與應(yīng)用,2020(03):31-32.林佳一.《Unity3D應(yīng)用開發(fā)》課程教學(xué)的探索和實(shí)踐[J].現(xiàn)代計(jì)算機(jī),2020(02):75-78.謝宏蘭.基于Unity3D射擊游戲的設(shè)計(jì)與實(shí)現(xiàn)[J].現(xiàn)代信息科技,2019,3(24):89-91+94.程弘霖,楊鍵,唐婭雯.基于Unity3D的VR求生游戲的研究與實(shí)現(xiàn)[J].信息與電腦(理論版),2019,31(24):88-91.陸生貴.無線游戲體感手柄的研究與設(shè)計(jì)[J].福建電腦,2019,35(12):62-65.區(qū)澤宇,李晶,魏菊霞,嚴(yán)道葵,陳燦,許皓然.基于Unity3D游戲的設(shè)計(jì)與開發(fā)[J].無線互聯(lián)科技,2019,16(23):62-63.郭子豪,李燦蘋.基于Unity3D引擎的吃豆人游戲設(shè)計(jì)[J].現(xiàn)代計(jì)算機(jī),2019(34):91-96.朱晴.Unity3D開發(fā)工具在3D游戲開發(fā)中的應(yīng)用[J].電子技術(shù)與軟件工程,2019(22):58-59.[10]王春艷,甘甜,吳倩蓮,王昱霖,高偉.基于Unity3D的VR英語教育游戲的設(shè)計(jì)與開發(fā)[J].計(jì)算機(jī)時代,2019(10):74-77.[11]王濤.基于Unity3DAR體感游戲的設(shè)計(jì)與實(shí)現(xiàn)[J].兵工自動化,2019,38(09):16-21.[12]ElizabethToriz.Learningbasedonflippedclassroomwithjust-in-time3D,gamificationandeducationalspaces[J].InternationalJournalonInteractiveDesignandManufacturing(IJIDeM),2019,13(3):12-34.[13]李昊宇.基于Unity3D的橫版過關(guān)游戲[J].電子制作,2019(16):46-48+92.[14]Lu.Zhang,LianShuan.Shi.ThePlatformDesignandImplementationofCampusFireSafetyKnowledgeBasedonUnity3D[J].ProcediaComputerScience,2019,154.[15]LiYunwang,DaiSumei,ShiYong,ZhaoLala,DingMinghua.NavigationSimulationofaMecanumWheelMobileRobotBasedonanImprovedA*AlgorithminUnity3D.[J].Sensors(Basel,Switzerland),2019,19(13):62-63.[16]UnityTechnologies.Unity4.X從入門到精通[M].天津:中國鐵道出版社,2013.11.28[17][美]史蒂夫·邁克康奈爾.《代碼大全(第二版)》[M].北京:電子工業(yè)出版社,2006[18]程杰.大話設(shè)計(jì)模式[M].北京:清華大學(xué)出版社,2007[19]羅培羽.Unity3D網(wǎng)絡(luò)游戲?qū)崙?zhàn)(第2版)[M].北京:機(jī)械工業(yè)出版社,2019[20]馮樂樂.UnityShader入門精要[M].北京:人民郵電出版社,2016[21]商宇浩.Unity5.x完全自學(xué)手冊[M].北京:電子工業(yè)出版社,2016[22]蔡升達(dá).設(shè)計(jì)模式與游戲完美開發(fā)[M].北京:清華大學(xué)出版社,2017[23][美]WendyDespain.游戲設(shè)計(jì)的100個原理[M].北京:人民郵電出版社,2015.[24][美]WendyDespain.游戲設(shè)計(jì)的100個原理[M].北京:人民郵電出版社,2015.[25][美]RobertSedgewick.算法[M].第4版.北京:人民郵電出版社,2012[26]朱柱.基于Unity3D的虛擬實(shí)驗(yàn)系統(tǒng)設(shè)計(jì)與應(yīng)用研究[D].武漢:華中師范大學(xué),2012.[27]ZhuoranLi,JingWang,MuhammadShahidAnwar,ZhongpengZheng.Anefficientmethodforgeneratingassemblyprecedenceconstraintson3Dmodelsbasedonablocksequencestructure[J].Computer-AidedDesign,2020,118.附錄源程序清單//怪物檢測publicclassMonsterWarn:CombatControl{publicGameObjectMonsteWeapon;privatevoidOnCollisionEnter(Collisioncollision){CombatDetection();}publicoverridevoidCombatDetection(){CollisionObject=1;}}//控制全局?jǐn)?shù)據(jù)publicclassGameDate:MonoBehaviour{publicstaticGameDateGame_data;publicfloat_DeffaultPlyerHp=200;publicint_DeffaultPlyerAttck=1;publicint_Score;publicCamera_camera;publicbool_IsUi=false;publicbool_IsMonUi=true;publicbool_isDamager=false;privatevoidAwake(){//實(shí)例化單例Game_data=this;//設(shè)置整數(shù)Application.targetFrameRate=120;_Score=0;Cursor.lockState=CursorLockMode.Locked;//Cursor.visible=false;//隱藏指針}}publicvoidAddMonsterControl(){gameObject.AddComponent<MonsterControl>();}publicvoidAddPlyerDefault(){gameObject.AddComponent<PlyerDefault>();}//戰(zhàn)斗控制//先對玩家和怪物進(jìn)行檢測然后進(jìn)行戰(zhàn)斗控制publicclassCombatControl:MonoBehaviour{publicintCollisionObject{get;set;}privatevoidUpdate(){Debug.Log(PlyerDefault.PlyerHp);AddDanmeger();}publicvirtualvoidCombatDetection(){Debug.LogWarning(PlyerDefault.PlyerHp);}//檢測到兩個接觸到了就會造成傷害voidAddDanmeger(){Debug.Log(CollisionObject);if(CollisionObject==2&&AnimationKey.damage==true){GameDate.Game_data._isDamager=true;AnimationKey.damage=false;CollisionObject=0;}}}//控制怪物自動巡邏、進(jìn)入/脫離戰(zhàn)斗、檢測敵人publicclassMonsterControl:MonoBehaviour{//publicList<object>test=newList<object>();[Header("設(shè)置需要控制的怪物")]//在面板里顯示一個標(biāo)題,這個標(biāo)題顯示在下方的第一個變量前面publicGameObjectmonsterObject;[Header("設(shè)置怪物預(yù)設(shè)血量")]publicfloatmonsterHP=100;[Header("設(shè)置怪物預(yù)設(shè)傷害")]publicstaticfloatmonsterDanger=1f;[Header("設(shè)置怪物預(yù)設(shè)移速")]publicfloatmonsterMoveSpeed=1f;[Header("設(shè)置怪物預(yù)設(shè)攻擊間隔")]publicfloatAttackTimeGap=2f;[Header("設(shè)置怪物遇敵顏色")]publicColordangerNameColor;[Header("設(shè)置怪物脫戰(zhàn)顏色")]publicColorsafetyNameColor;[Header("設(shè)置怪物預(yù)設(shè)攻擊間隔")]publicfloatfollowDistance=2f;[Header("設(shè)置需要移動的路徑點(diǎn)")]//數(shù)組只能查、改,鏈表可以增、刪、查、改publicList<Transform>aiPatrolPath=newList<Transform>();[Header("設(shè)置怪物需要搜索的層")]publicLayerMasklayer;publicintlayervalue=0;[Header("設(shè)置怪物搜索的范圍")]publicintdangerRange=4;[Header("設(shè)置脫離戰(zhàn)斗距離")]publicintsafetyRange=8;[Header("Canvas")]publicCanvascanvas;[Header("設(shè)置怪物預(yù)設(shè)名稱")]publicstringmonsterName;[Header("設(shè)置怪物預(yù)設(shè)等級")]publicintmonsterLevel;[Header("設(shè)置怪物UI的偏移")]publicVector3uIPosOffset=newVector3(0,1,0);//[Header("設(shè)置怪物名稱3D文本看向的攝像機(jī)")]//publicCameratargetCamera;[Header("怪物決斷參數(shù)(無需設(shè)置)")]publicboolIsCombat=true;publicintpath=0;//記錄路徑點(diǎn)的值publicCollider[]plyer;//記錄相交球碰撞信息publicintrangeValue;//接受碰撞變化的值publicTransformNewPath;//用來添加新路徑點(diǎn)publicAnimatormonsterAima;//動畫組件publicboolisFollow=true;//用來判斷怪物追擊publicfloatAttackTimeGapValue=0f;//用來記錄間隔時間privateGameObjectui_Clon;//克隆UIpublicfloatuIShowDis=15f;//用來控制血條顯示距離publicfloatuIScale=2f;//用來控制血條縮放系數(shù)publicintIsUIScaleSwitch=0;privatefloatmonsterHPMax;//用來記錄怪物的滿血狀態(tài)privatevoidAwake(){ClonUI();dangerNameColor=Color.red;safetyNameColor=Color.green;//獲取拖拽進(jìn)來的怪物的動畫組件monsterAima=monsterObject.GetComponent<Animator>();LogError();monsterHPMax=monsterHP;}voidUpdate(){Debug.Log(monsterObject);//調(diào)用自動巡邏方法AutoPatrol();//怪物警戒InsightFoe();die();IsDamager();}privatevoidLateUpdate(){//怪物名稱的展示MonsterName();ClonUIImagerValue();IsMonsterUi();}voidAutoPatrol(){//沒有檢測到玩家時進(jìn)入巡邏if(IsCombat==true){//巡邏時,怪物名字顏色ui_Clon.transform.GetChild(1).transform.GetChild(0).GetComponent<Text>().color=safetyNameColor;//縮小觸發(fā)戰(zhàn)斗碰撞rangeValue=dangerRange;//動畫狀態(tài)機(jī)monsterAima.SetBool("IsAttck_Run",false);//移動到指定路徑點(diǎn)monsterObject.transform.position=Vector3.MoveTowards(monsterObject.transform.position,newVector3(aiPatrolPath[path].transform.position.x,monsterObject.transform.position.y,aiPatrolPath[path].transform.position.z),Time.deltaTime*monsterMoveSpeed*.4f);//轉(zhuǎn)向下一個路徑點(diǎn)monsterObject.transform.LookAt(newVector3(aiPatrolPath[path].transform.position.x,monsterObject.transform.position.y,aiPatrolPath[path].transform.position.z));//判斷是否移動路徑點(diǎn),然后轉(zhuǎn)向下一路徑點(diǎn)if(Vector3.Distance(monsterObject.transform.position,aiPatrolPath[path].transform.position)<=.5f){path++;}//歸零路徑點(diǎn),循環(huán)巡邏if(path==aiPatrolPath.Count){path=0;}}//檢測到玩家時elseif(IsCombat==false){//戰(zhàn)斗時怪物名字顏色ui_Clon.transform.GetChild(1).transform.GetChild(0).GetComponent<Text>().color=dangerNameColor;//擴(kuò)大脫離戰(zhàn)斗碰撞rangeValue=safetyRange;//始終看向玩家monsterObject.transform.LookAt(newVector3(plyer[0].gameObject.transform.position.x,monsterObject.transform.position.y,plyer[0].gameObject.transform.position.z));//計(jì)算玩家與怪物之間的距離floatdistance=Vector3.Distance(monsterObject.transform.position,plyer[0].transform.position);//如果玩家與怪物之間距離大于1if(distance>1f&&isFollow==true){//動畫狀態(tài)機(jī)的控制monsterAima.SetBool("IsAttck_Run",true);monsterAima.SetBool("IsAttck_Idle",false);//移動到指定路徑點(diǎn)monsterObject.transform.position=Vector3.MoveTowards(monsterObject.transform.position,newVector3(plyer[0].gameObject.transform.position.x,monsterObject.transform.position.y,plyer[0].gameObject.transform.position.z),Time.deltaTime*monsterMoveSpeed);}//如果玩家與怪物之間距離小于1if(distance<=1f){//關(guān)閉追擊isFollow=false;//動畫狀態(tài)機(jī)控制monsterAima.SetBool("IsAttck_Idle",true);monsterAima.SetBool("IsAttck_Run",false);monsterAima.SetFloat("IsAttck",AttackTimeGapValue);//如果計(jì)時器大于指定間隔,執(zhí)行一次攻擊if(monsterAima.GetFloat("IsAttck")>AttackTimeGap){PlyerDefault.PlyerHp-=MonsterControl.monsterDanger;AttackTimeGapValue=0;}}//如果玩家距離與怪物距離大于2if(distance>followDistance&&isFollow==false){//開始追擊isFollow=true;//計(jì)時器歸零AttackTimeGapValue=0;}//調(diào)用計(jì)時協(xié)程StartCoroutine(timeLoad());}}//通過協(xié)程(多線程)計(jì)時來決定攻擊的時間間隔IEnumeratortimeLoad(){yieldreturnAttackTimeGapValue+=Time.deltaTime;}//怪物檢測玩家voidInsightFoe(){//通過相交球檢測玩家是否處在怪物警戒范圍plyer=Physics.OverlapSphere(monsterObject.transform.position,rangeValue,layer=1<<layervalue);//如果檢測到玩家,中斷巡邏if(plyer.Length!=0){IsCombat=false;}//如果玩家離開戰(zhàn)斗范圍,重新回到巡邏else{IsCombat=true;}}//怪物UI配置voidMonsterName(){//轉(zhuǎn)換怪物為屏幕坐標(biāo)Vector3pos=Camera.main.WorldToScreenPoint(monsterObject.transform.position+uIPosOffset)+newVector3(-Screen.width*.5f,-Screen.height*.5f);//讓ui的屏幕位置等于怪物的屏幕坐標(biāo)位置ui_Clon.transform.localPosition=pos;//獲取攝像機(jī)的向量TransformcamPos=Camera.main.transform;//如果腳本上選擇的是默認(rèn)縮放模式if(IsUIScaleSwitch==0){//讓UI根據(jù)距離遠(yuǎn)近適當(dāng)縮放ui_Clon.transform.localScale=(newVector3(1f,1f,1)/Vector3.Distance(camPos.position,monsterObject.transform.position)*uIScale);}//將怪物的3D坐標(biāo)位置減去攝像機(jī)的位置,并且歸一化向量Vector3dir=(monsterObject.transform.position-camPos.position).normalized;//將攝像機(jī)的位置與單位向量點(diǎn)積運(yùn)算,判斷怪物是否在攝像機(jī)前方floatdot=Vector3.Dot(camPos.forward,dir);//如果滿足怪物在攝像機(jī)前方而且還在指定范圍內(nèi)if(dot>0&&Vector3.Distance(camPos.position,monsterObject.transform.position)<uIShowDis){//那么顯示UIui_Clon.SetActive(true);}//否則不顯示elseui_Clon.SetActive(false);}//克隆ui并獲取生成信息publicvoidClonUI(){GameObjectloadUI=(GameObject)Resources.Load("Monster_UI");ui_Clon=Instantiate(loadUI);ui_C=monsterO;ui_Clon.transform.SetParent(canvas.transform);ui_Clon.transform.GetChild(1).transform.GetChild(0).GetComponent<Text>().text=monsterName;ui_Clon.transform.GetChild(2).transform.GetChild(0).GetComponent<Text>().text=monsterLevel.ToString();}//血條publicvoidClonUIImagerValue(){ui_Clon.transform.GetChild(1).transform.GetComponent<Image>().fillAmount=monsterHP/monsterHPMax;}//在編輯場景中繪制相交球voidOnDrawGizmos(){Gizmos.color=Color.red;Gizmos.DrawSphere(monsterObject.transform.position,rangeValue);}//用來在編輯模式下創(chuàng)建新路徑點(diǎn)的方法publicvoidaddPath(){aiPatrolPath.Add(NewPath);}//用來在編輯模式下刪除路徑點(diǎn)的方法publicvoidRemovePath(){for(inti=0;i<aiPatrolPath.Count;i++){if(i==aiPatrolPath.Count-1){aiPatrolPath.Remove(aiPatrolPath[i]);}}}//publicvoiddie(){if(monsterHP<=0){GameDate.Game_data._Score++;Destroy(monsterObject);Destroy(ui_Clon);}}publicvoidIsMonsterUi(){if(GameDate.Game_data._IsMonUi==true){ui_Clon.SetActive(true);}elseif(GameDate.Game_data._IsMonUi==false){ui_Clon.SetActive(false);}}publicvoidIsDamager(){if(GameDate.Game_data._isDamager==true){monsterHP-=PlyerDefault.PlyerAttck;GameDate.Game_data._isDamager=false;}}publicvoidLogError(){if(canvas==null){Debug.LogError("還沒有在腳本中指定UI圖層即Canvas");}if(monsterObject==null){Debug.LogError("還沒有指定游戲?qū)ο?);}if(aiPatrolPath.Count>1){Debug.Log("還沒有在腳本中指定路徑點(diǎn)");}if(layervalue==0){Debug.LogError("還沒有配置搜索層級");}}//玩家的行為樹publicclassPlayerContor:MonoBehaviour{[Header("獲取Animator組件")][Space][Tooltip("獲取到的動畫狀態(tài)機(jī)")][Space]publicAnimatorplayerAnimatorContor;[Header("行為樹X和Y的參數(shù)")][Space][SerializeField]privatefloatxValue;[SerializeField]privatefloatyValue;[Header("角色動作狀態(tài)")][Space]privatefloatstateValue;[Header("角色旋轉(zhuǎn)時的移動速度")][Space]publicfloatmoveSpeed_Rotate=.3f;[Header("角色行走時的移動速度")][Space]publicfloatmoveSpeed_Walk=.6f;[Header("角色奔跑時的移動速度")][Space]publicfloatmoveSpeed_Run=2.5f;[Header("角色攻擊狀態(tài)時的移動速度")][Space]publicfloatmoveSpeed_Attack=1.7f;voidAwake(){//獲取模型Animator組件playerAnimatorContor=this.gameObject.GetComponent<Animator>();//行為樹x和y的默認(rèn)值xValue=0;yValue=0;//設(shè)置角色默認(rèn)行為狀態(tài)stateValue=0;}voidUpdate(){//調(diào)用綁定XY的行為樹方法Ainima_Contor();//調(diào)用按鍵控制和邏輯判斷方法Button_Contor();//執(zhí)行關(guān)鍵幀事件(在播放指定放動畫時不能移動)if(AnimationKey.IsOverIdle==true){//調(diào)用移動速度方法Move_Contor();}}//把xValue和yValue綁定給行為樹的X和YprivatevoidAinima_Contor(){playerAnimatorContor.SetFloat("X",xValue);playerAnimatorContor.SetFloat("Y",yValue);}//移動速度的方法privatevoidMove_Contor(){//如果鼠標(biāo)橫向拖動距離等于一定值,且玩家角色狀態(tài)大于0if(Input.GetAxis("MouseX")>0.8f||Input.GetAxis("MouseX")<-.8f||stateValue>0){//讓角色的旋轉(zhuǎn)角度等于鼠標(biāo)拖動的距離this.gameObject.transform.Rotate(newVector3(0,Input.GetAxis("MouseX"),0));//如果角色是待機(jī)狀態(tài)if(stateValue==0){//設(shè)置移動速度this.transform.Translate(Vector3.forward*moveSpeed_Rotate*Time.deltaTime,Space.Self);//讓待機(jī)旋轉(zhuǎn)時播放行走動畫playerAnimatorContor.SetBool("IsWalk",true);}//如果角色是步行狀態(tài)if(stateValue==1){//設(shè)置前進(jìn)和左右轉(zhuǎn)移動速度if(Input.GetKey(KeyCode.W)){this.transform.Translate(Vector3.forward*moveSpeed_Walk*Time.deltaTime,Space.Self);if(Input.GetKey(KeyCode.A)){this.transform.Translate(newVector3(-1,0,0)*moveSpeed_Walk*Time.deltaTime,Space.Self);}elseif(Input.GetKey(KeyCode.D)){this.transform.Translate(newVector3(1,0,0)*moveSpeed_Walk*Time.deltaTime,Space.Self);}}//設(shè)置后退和左右轉(zhuǎn)移動速度elseif(Input.GetKey(KeyCode.S)||Input.GetKey(KeyCode.LeftShift)){this.transform.Translate(Vector3.back*moveSpeed_Walk*Time.deltaTime*1f,Space.Self);if(Input.GetKey(KeyCode.A)){this.transform.Translate(newVector3(-1,0,0)*moveSpeed_Walk*Time.deltaTime,Space.Self);}elseif(Input.GetKey(KeyCode.D)){this.transform.Translate(newVector3(1,0,0)*moveSpeed_Walk*Time.deltaTime,Space.Self);}}}//如果角色是奔跑狀態(tài)if(stateValue==2){//設(shè)置前進(jìn)和左右轉(zhuǎn)移動速度if(Input.GetKey(KeyCode.W)){this.transform.Translate(Vector3.forward*moveSpeed_Run*Time.deltaTime,Space.Self);if(Input.GetKey(KeyCode.A)){this.transform.Translate(newVector3(-1,0,0)*moveSpeed_Run*Time.deltaTime,Space.Self);}elseif(Input.GetKey(KeyCode.D)){this.transform.Translate(newVector3(1,0,0)*moveSpeed_Run*Time.deltaTime,Space.Self);}}}if(stateValue==3){//設(shè)置前進(jìn)和左右轉(zhuǎn)移動速度if(Input.GetKey(KeyCode.W)){this.transform.Translate(Vector3.forward*moveSpeed_Attack*Time.deltaTime,Space.Self);if(Input.GetKey(KeyCode.A)){this.transform.Translate(newVector3(-1,0,0)*moveSpeed_Attack*Time.deltaTime*.7f,Space.Self);}elseif(Input.GetKey(KeyCode.D)){this.transform.Translate(newVector3(1,0,0)*moveSpeed_Attack*Time.deltaTime*.7f,Space.Self);}}elseif(Input.GetKey(KeyCode.S)){if(xValue==0){this.transform.Translate(Vector3.back*moveSpeed_Attack*Time.deltaTime*.4f,Space.Self);}else{playerAnimatorContor.SetBool("IsWalk",false);}if(yValue<0){xValue=0;this.transform.Translate(Vector3.back*moveSpeed_Attack*Time.deltaTime*.4f,Space.Self);}}}}}//動畫按鈕狀態(tài)和邏輯判斷privatevoidButton_Contor(){//基礎(chǔ)移動控制——如果按下W或者Sif(Input.GetKey(KeyCode.W)||Input.GetKey(KeyCode.S)){//此時狀態(tài)為行走狀態(tài)if(playerAnimatorContor.GetBool("IsDraw")==true){stateValue
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 多平臺協(xié)作下的現(xiàn)代酒店數(shù)字化服務(wù)平臺構(gòu)建策略探討
- 教育領(lǐng)域的專家對家庭教育的看法與建議
- 教育機(jī)構(gòu)中的安全消防教育與實(shí)踐探索
- 教育領(lǐng)域中的環(huán)境藝術(shù)設(shè)計(jì)及其現(xiàn)場繪畫實(shí)踐
- 教育機(jī)構(gòu)消防設(shè)施日常維護(hù)
- 2025年度舞蹈教練舞蹈教學(xué)版權(quán)使用合同3篇
- 打造健康家居環(huán)境有效預(yù)防傳染病傳播
- 2025年房屋及土地使用權(quán)共有權(quán)轉(zhuǎn)移協(xié)議3篇
- Module6 Unit1 Ive got some Chinese chopsticks.(說課稿)-2024-2025學(xué)年外研版(一起)英語六年級上冊
- 2025年度銅門行業(yè)產(chǎn)業(yè)鏈整合與資源優(yōu)化合同2篇
- 餐飲行業(yè)智慧餐廳管理系統(tǒng)方案
- 2025年度生物醫(yī)藥技術(shù)研發(fā)與許可協(xié)議3篇
- 電廠檢修安全培訓(xùn)課件
- 殯葬改革課件
- 2024企業(yè)答謝晚宴會務(wù)合同3篇
- 雙方個人協(xié)議書模板
- 車站安全管理研究報(bào)告
- 瑪米亞RB67中文說明書
- 五年級數(shù)學(xué)(小數(shù)四則混合運(yùn)算)計(jì)算題專項(xiàng)練習(xí)及答案
- 2024年鋼鐵貿(mào)易行業(yè)前景分析:鋼鐵貿(mào)易行業(yè)發(fā)展趨勢推動行業(yè)可持續(xù)發(fā)展
- 節(jié)前物業(yè)安全培訓(xùn)
評論
0/150
提交評論