版本記錄
| 版本號 | 時間 |
|---|---|
| V1.0 | 2018.12.17 星期一 |
前言
Unity是由Unity Technologies開發(fā)的一個讓玩家輕松創(chuàng)建諸如三維視頻游戲、建筑可視化、實時三維動畫等類型互動內(nèi)容的多平臺的綜合型游戲開發(fā)工具,是一個全面整合的專業(yè)游戲引擎。Unity類似于Director,Blender game engine, Virtools 或 Torque Game Builder等利用交互的圖型化開發(fā)環(huán)境為首要方式的軟件。其編輯器運行在Windows 和Mac OS X下,可發(fā)布游戲至Windows、Mac、Wii、iPhone、WebGL(需要HTML5)、Windows phone 8和Android平臺。也可以利用Unity web player插件發(fā)布網(wǎng)頁游戲,支持Mac和Windows的網(wǎng)頁瀏覽。它的網(wǎng)頁播放器也被Mac 所支持。網(wǎng)頁游戲 坦克英雄和手機游戲王者榮耀都是基于它的開發(fā)。
下面我們就一起開啟Unity之旅。感興趣的看下面幾篇文章。
1. Unity開啟篇(一) —— Unity界面及創(chuàng)建第一個簡單的游戲 (一)
2. Unity開啟篇(二) —— Unity界面及創(chuàng)建第一個簡單的游戲 (二)
3. Unity開啟篇(三) —— 一款簡單射擊游戲示例 (一)
4. Unity開啟篇(四) —— 一款簡單射擊游戲示例 (二)
開始
首先看一下本文的寫作環(huán)境
C# 7.2, Unity 2018.1, Unity
歡迎來到Unity迷你系列的第三部分也是最后一部分!在本教程中,您將學習Unity中的所有組件(Components),同時讓您的英雄自由用子彈設(shè)計物體!
在這一點上,你已經(jīng)完成了讓所有主要角色都做好準備的目標,但它本質(zhì)上是一個空洞的舞臺。
在本教程中,您將通過使用組件(Components)為游戲添加一些交互性,這些組件是Unity游戲開發(fā)的基礎(chǔ)。如果您將GameObject視為名詞,那么組件將是動詞或執(zhí)行動作的部分;組件代表GameObject執(zhí)行某些操作。
你已經(jīng)學會了一些關(guān)于組件的知識。在本系列教程的前兩部分中,您了解了每個GameObject如何具有一個必需組件:Transform組件,它存儲GameObject的位置,旋轉(zhuǎn)和縮放。

但Unity提供的組件遠不止于此。 例如,有一個light組件可以照亮它附近的任何東西。 有一個會產(chǎn)生聲音的audio source組件。 甚至還有一個particle system組件會產(chǎn)生一些令人印象深刻的視覺效果。 當然,如果沒有一個組件能夠滿足您的需求,您可以編寫自己的組件。
在本教程中,您將了解幾種類型的組件,包括Rigidbody組件,script組件等。 在本教程結(jié)束時,您的海軍陸戰(zhàn)隊員將會開始行動并開槍!
如果您完成了上一個教程,請打開當前的Bobblehead Wars項目,以便從中斷的地方繼續(xù)學習。
目前,海軍陸戰(zhàn)隊員只知道如何像雕像一樣站立。 如果他要避免成為外星人的零食,他需要四處走動。
你要添加的第一件事是一個Rigidbody組件,它將GameObject選入物理引擎。 通過添加它,您將啟用GameObject與其他GameObjects的碰撞。
Adding the Rigidbody Component - 添加Rigidbody組件
在Hierarchy中,選擇SpaceMarine GameObject,然后單擊Inspector中的Add Component按鈕。

你會看到許多不同的類別。 當您知道所需的組件時,只需按名稱搜索即可。 否則,請選擇其中一個類別并選擇最佳選項。

單擊Physics類別,然后選擇Rigidbody。

你會看到一個Rigidbody組件被附加到GameObject上。恭喜! 您添加了第一個組件。

每個組件都有自己的一組屬性,值等。 可以在Inspector或代碼中更改這些屬性。 組件也有自己的圖標,以便于一目了然地確定其類型。

您會注意到每個組件右上角的一些圖標,如下所示:

第一個圖標是Reference圖標。 點擊它。 它將打開另一個窗口,其中包含該組件的文檔頁面。 如果您安裝了文檔,則此頁面位于您的計算機上 - 是的,搜索欄可以正常工作。

第二個圖標是Unity 2018中的新功能。這是預設(shè)presets按鈕。 在自定義組件時,您可能更喜歡先前創(chuàng)建的某個預設(shè)配置。
在Rigidbody組件中,選中IsKinematic復選框。 此外,取消選中Use Gravity選項。 您馬上就會了解這些選項。 但是,一旦取消選中它們,請單擊presets按鈕。

您可以將該配置保存為預設(shè),然后根據(jù)需要切換到該預設(shè)。 您還可以使用指定的預設(shè)創(chuàng)建新的GameObject,從而節(jié)省您的時間。

此對話框?qū)⒘谐鏊蓄A設(shè)。 單擊Save current to and from the Project Browser,然后選擇Presets文件夾。 稱之為運動學(Kinematic)。 現(xiàn)在當您再次單擊預設(shè)按鈕時,您將看到新保存的預設(shè)。 當您想要進行更改時,預設(shè)是保存當前配置設(shè)置的好方法。
組件右上角的三個按鈕中的最后一個是齒輪圖標。 點擊它。 此對話框?qū)⒊霈F(xiàn):

以下是此處列出的最重要選項:
- Reset會將組件重置為其默認值。
- Move to Front 和 Move to Back調(diào)整2D游戲中精靈的順序。
-
Remove Component將從
GameObject中刪除組件 - 您可以撤消此操作。 -
Copy Component允許您從一個
GameObject復制組件并將其粘貼到另一個GameObject上。 - Paste Component as New會將復制的組件粘貼到GameObject。
- Paste Component Values允許您從復制的組件覆蓋當前組件的值。具體來說,您可以在游戲進行時復制組件的值。停止游戲后,您可以將這些值粘貼到另一個組件上。這非常有用,因為有時候在玩游戲時調(diào)整一些東西是很有用的。
從菜單中,選擇remove component?,F(xiàn)在再次單擊add component按鈕,然后將Rigidbody組件添加回GameObject。請記住,它屬于Physics類別。最后,單擊presets按鈕并選擇Kinematic預設(shè)。
請注意,Rigidbody組件是根據(jù)您的預設(shè)自動神奇更新的。但你可能會問,什么是Rigidbody?
通過將Rigidbody組件添加到陸戰(zhàn)隊員中,您已經(jīng)做到了這一點,以便他現(xiàn)在可以響應碰撞事件并響應重力。但是,你不希望他從敵人或墻壁上彈跳。你肯定想知道那些碰撞事件,但是你不希望英雄因為碰到一個列而失控。
isKinematic屬性告訴物理引擎你手動控制陸戰(zhàn)隊員,而不是讓物理引擎為你移動陸戰(zhàn)隊員。但物理引擎仍然知道陸戰(zhàn)隊員的位置以及它何時與某些東西發(fā)生碰撞。這是有幫助的,這樣當陸戰(zhàn)隊員與外星人碰撞時,物理引擎會通知你,這樣你就可以發(fā)生一些事情 - 比如陸戰(zhàn)隊員變得更加緊張!
通過取消選中Use Gravity選項,陸戰(zhàn)隊員不會受到重力的影響。再次 - 您不需要這個,因為您將手動移動陸戰(zhàn)隊員并且僅使用Rigidbody進行碰撞檢測。
現(xiàn)在來到有趣的部分:是時候制作陸戰(zhàn)隊員舞了!或者移動。那也沒關(guān)系。
Unity提供了一些內(nèi)置組件,使移動變得簡單。但出于學習目的,在本教程中。你將通過腳本的力量手動完成所有事情。
Introducing Scripting - 引入腳本
對于非程序員來說,腳本編寫充其量只是一個很小的障礙。
來自藝術(shù)背景,我可以說腳本并不像你想象的那么難。 像任何事情一樣,只需要一些時間和耐心來理解它是如何工作的。
在本教程中,您將使用C#編寫腳本,C#是Microsoft開發(fā)的一種流行語言,適用于移動和桌面應用程序。 它功能豐富,功能齊全。 不幸的是,我無法在本教程中教授所有內(nèi)容。

它專為非程序員設(shè)計,并在Unity環(huán)境中進行教學。
如果你是編程的初學者,一定要先檢查一下。如果您是一位經(jīng)驗豐富的開發(fā)人員,或者是一位特別勇敢的初學者,請隨時繼續(xù),因為本教程中的所有內(nèi)容都是一步一步的;只要明白,沒有C#知識,你的理解可能會有一些差距。
1. Why Not JavaScript? - 為什么不是JavaScript?
在當天,Unity發(fā)布了Javascript和一個名為Boo的python變種。大多數(shù)開發(fā)人員在2017年使用C#,因此Javascript的支持被刪除了。幾年前Boo被棄用了?,F(xiàn)在,所有腳本都完全用C#完成。
您可能會遇到引用Javascript的教程,但您甚至無法在編輯器中創(chuàng)建Javascript文件。這是一件好事,因為Unity已經(jīng)專注于他們的C#實現(xiàn),將其更新為近乎現(xiàn)代的語言版本。
C#可能需要一些時間來學習,但您可以利用Unity以外的編程技能。例如,如果您發(fā)現(xiàn)自己不喜歡游戲開發(fā)(或者很難謀生)而是喜歡這種語言,那么您可以將這些技能轉(zhuǎn)換為C#開發(fā)工作,創(chuàng)建桌面或移動應用程序,甚至開發(fā)后端服務器應用程序。
編碼在Unity中的工作方式是您創(chuàng)建scripts。scripts只是您附加到GameObjects的另一種類型的組件,您可以編寫代碼。
腳本派生自一個名為MonoBehaviour的類,您可以覆蓋多個方法以獲取特定事件的通知:
-
Update():此事件發(fā)生在每一幀。如果你的游戲以每秒60幀的速度運行,則
Update()被調(diào)用60次。毋庸置疑,您不希望在此方法中進行任何繁重的處理。 - OnEnable():當啟用GameObject時以及非活動GameObject突然重新激活時調(diào)用。通常,當您暫時不需要它們但稍后需要時,您將停用GameObjects。
-
Start():在腳本的生命周期和調(diào)用
Update()之前調(diào)用一次。這是進行設(shè)置和初始化的好地方。 - Destroy():在對象進入GameObject之前調(diào)用它。這是一個清理的好地方,例如關(guān)閉網(wǎng)絡連接。
您將在本教程中發(fā)現(xiàn)許多其他事件。要查看完整列表,請訪問Unity網(wǎng)站上的MonoBehavior參考:
Creating Your First Script - 創(chuàng)建你的第一個腳本
好戲開場了!
您可以使用許多選項來創(chuàng)建腳本。 您可以單擊Add Component按鈕,然后選擇New Script。
但我希望您這樣嘗試:在項目瀏覽器中選擇Scripts文件夾,然后單擊Create按鈕。 從下拉菜單中選擇C#Script并將其命名為PlayerController。
您將在Scripts文件夾中看到新腳本。 將它從Scripts文件夾拖到SpaceMarine GameObject上。
您現(xiàn)在應該看到腳本列為層次結(jié)構(gòu)中SpaceMarine GameObject的組件之一。

您已添加了第一個自定義組件! 當然,它沒有做任何事情......
在你做之前,你會在短時間內(nèi)改變它,你需要了解Input Manager。
Managing Input - 管理輸入
輸入是游戲的控件,如果您正在為臺式計算機開發(fā)游戲,您的用戶將期望能夠重新綁定鍵。 Unity的Input Manager使這很簡單,是游戲處理用戶輸入的首選方式。
要訪問Input Manager,請單擊Edit\Project Settings\Input。
Inspector看起來很空。 單擊單詞Axes旁邊的顯示三角形。

展開后,您將看到可供您使用的所有預配置輸入。

第一個屬性是Size,它是您的游戲使用的輸入數(shù)量。 您可以減少數(shù)量,并在需要更多輸入時增加數(shù)量。 目前的投入量足以滿足這個游戲的需求。
單擊Horizontal旁邊的顯示三角形。 在這里,您可以配置水平軸的輸入,即左或右。

下面進行詳細說明:
-
Name是Unity提供輸入的名稱。此示例稱為
“Horizontal”,但您可以將其稱為任何名字。這也是您在代碼中引用的名稱,稍后您將看到。 -
Descriptive Name and Negative Name是Unity游戲啟動器中的用戶想要重新映射密鑰的名稱。如果您愿意,可以禁用Unity游戲啟動并提供您自己的鍵映射界面,因此這些不是必需屬性。
+ * Negative和Positive Buttons是正在使用的實際鍵。 Unity允許按鈕具有負或相反的鍵。例如,右箭頭鍵為正,而左箭頭鍵為負。您不需要為所有鍵提供負數(shù) - 為使用操作提供負鍵是沒有意義的。+ * Alt Negative和Alt Positive Buttons是替代鍵。在這種情況下,您可以啟用A和D鍵,而不是左箭頭鍵和右箭頭鍵。
其他的field主要涉及模擬棒(analog sticks)的功能。為簡單起見,此游戲僅使用鍵盤輸入。如果你想讓這款游戲成為一款真正的雙棒射擊游戲,你可以選擇這些游戲來制定嚴格的控制方案。
Accessing Input From Code - 從代碼獲取輸入
現(xiàn)在實際實現(xiàn)控制方案。 在項目瀏覽器中,雙擊PlayerController腳本以啟動編輯器。
代碼編輯器打開后,您將看到第一個腳本。 每個新腳本都包含Start()和Update()的空實現(xiàn)。
在第一個{(a.k.a。,“花括號”)下面找一個空白行 - 這就是類定義。 在那里添加以下代碼:
public float moveSpeed = 50.0f;
注意:如果您不熟悉編程語言,那么將所有內(nèi)容完全按照編寫方式進行復制至關(guān)重要。 任何偏差都會產(chǎn)生錯誤。 編程語言非常精確,當您使用不正確的大小寫或語法時會變得脾氣暴躁。
如果您的腳本引發(fā)錯誤,請仔細查看代碼以確保您不會錯過,忘記或搞砸某些內(nèi)容。
moveSpeed是一個變量,用于確定英雄在競技場中移動的速度。 您將其設(shè)置為默認值50,您可以稍后在Unity的界面中進行更改。
現(xiàn)在,編寫實際的移動代碼。 在Update()中,添加以下內(nèi)容:
Vector3 pos = transform.position;
這段代碼只是獲取當前GameObject的當前位置 - 在這種情況下,陸戰(zhàn)隊員因為這是該腳本所附加的 - 并將其存儲在名為pos的變量中。 在Unity中,Vector3封裝了GameObject的x,y和z,即3D空間中對象的點。
現(xiàn)在是棘手的部分。 在上一行之后添加以下內(nèi)容:
pos.x += moveSpeed * Input.GetAxis("Horizontal") * Time.deltaTime;
pos.z += moveSpeed * Input.GetAxis("Vertical") * Time.deltaTime;
移動對象時,它只會在z軸和x軸上,因為y表示向上和向下。 因為有兩個不同的輸入源(左右為“水平”,向上和向下為“垂直”),所以需要分別計算每個軸的值。
Input.GetAxis(“Horizontal”)從Input Manager的Horizontal組件中檢索值。 返回的值為1或-1,其中1表示正在按下輸入管理器中的正按鈕。 根據(jù)您之前定義的設(shè)置,這是右箭頭或d鍵。 類似地,值-1表示正在按下負按鈕,這意味著它是左箭頭或a鍵。

無論返回的值是什么,它都會乘以moveSpeed并添加到GameObject的當前x位置,從而有效地將其移動到所需的方向。
Input.GetAxis(“Vertical”)也會發(fā)生同樣的事情,除了它從Input Manager的垂直組件中檢索一個值(表示s,down,w或up鍵),將此值(1或-1)乘以moveSpeed并將其添加到GameObject的z位置。
那么Time.deltaTime是什么?該值表示自上次Update()以來經(jīng)過了多長時間。請記住,每個幀都會調(diào)用Update(),因此必須考慮時間差異,或者陸戰(zhàn)隊員移動得太快而無法看到。
TL / DR:Time.deltaTime確保移動與幀速率同步。
這些數(shù)字是什么意思?
默認情況下,Unity認為一個點等于一米,但您不必遵循此邏輯。例如,你可能正在制作一個關(guān)于行星的游戲,而且這個尺度太小了。為了簡化本教程,我們調(diào)整了模型的大小,以遵循Unity默認的每米一點。
現(xiàn)在您已經(jīng)更改了位置,您必須將它應用于SpaceMarine GameObject。在上一行之后添加以下內(nèi)容:
transform.position = pos;
這會使用新位置更新SpaceMarine GameObject的位置。
保存腳本并切換回Unity。 你可能很想運行你的游戲,但是有一個小問題。 相機未正確放置。
在Hierarchy中,選擇Main Camera,在Inspector中,將Position設(shè)置為(-9.7,53.6,-56.1),將Rotation設(shè)置為(30,0,0)。 我通過手動移動相機并查看右下角的相機預覽來確定這些值,直到我對結(jié)果感到滿意為止。
在Camera組件中,將Field of View設(shè)置為31。這樣可以有效地“放大”視圖。

現(xiàn)在是時候讓你的游戲進行試運行了。 在編輯器的中心頂部查找播放控件。 單擊Play按鈕。

注意:您會注意到控件還有兩個選項:
Pause和pause stepper。 暫??勺屇鷷和S螒颉?stepper允許您一次一幀地逐步執(zhí)行動畫,這對于調(diào)試動畫問題特別有用。

現(xiàn)在,查看游戲窗口并按箭頭鍵或WASD鍵移動角色。
The Game window - 游戲窗口
游戲窗口是您實際玩游戲的地方。玩游戲時要記住兩個生死的細節(jié)。
首先,當您開始播放時,界面會變暗,以提供您正在播放模式的可視隊列。
第二,當你玩游戲時。您可以更改任何內(nèi)容(包括更改檢查器中組件的值),但是當您停止玩游戲時,所有更改都將丟失。這既是一種好處,也是一種壞處。好處是你有能力調(diào)整游戲而沒有后果。壞處是,有時你會忘記你處于游戲模式,繼續(xù)你的游戲,然后由于某種原因,游戲停止。噗!再見!
值得慶幸的是,您可以(并且應該)使播放模式非常明顯。選擇PC上的
Edit \ Preferences或Mac上的Unity \ Preferences以顯示選項列表。選擇
Colors部分。尋找Playmode色調(diào)。單擊它旁邊的顏色框,然后給它一個明確無誤的顏色 - 我更喜歡紅色。現(xiàn)在玩你的游戲,看看它是否足夠顯眼。
Camera Movement - 相機運動
陸戰(zhàn)隊員的運動只有一個問題:他會從屏幕上滑落。 你希望相機跟隨競技場周圍的英雄,所以他不會離你而去。
通過一些腳本編寫,您可以保持對陸戰(zhàn)隊員的關(guān)注。
首先,確保您沒有處于游戲模式 - 要停止游戲模式,請再次選擇play按鈕。
在“層次結(jié)構(gòu)”中,單擊“創(chuàng)建”按鈕,然后選擇Create Empty。 將其命名為CameraMount。
基本思路是您希望CameraMount表示相機應該關(guān)注的位置,并讓相機相對于此位置。
最初你希望相機聚焦在太空船的位置,所以讓我們將CameraMount配置在與太空船的完全相同的位置。
要執(zhí)行此操作,請選擇space marine,單擊Transform組件右上角的齒輪按鈕,然后選擇Copy Component

然后選擇CameraMount,單擊Transform組件右上角的齒輪按鈕,然后選擇Paste Component Values:
接下來,將Main Camera GameObject拖動到CameraMount GameObject中。

很好! 現(xiàn)在,當你移動玩家時,你可以移動CameraMount與玩家一起移動,相機將跟蹤玩家。 您只需要編寫一個腳本來執(zhí)行此操作。
選擇CameraMount后,單擊“檢查器”中的Add Component按鈕,然后選擇New Script。 將其命名為CameraMovement,然后單擊Create and Add。
注意:通過單擊
Add Component按鈕創(chuàng)建新腳本時,Unity將在資源文件夾的頂級創(chuàng)建腳本。 養(yǎng)成在制作或查看資源時將資源移動到各自文件夾中的習慣。
將新文件從assets文件夾的頂級拖到Scripts文件夾中。
雙擊CameraMovement腳本以在代碼編輯器中將其打開。 在類定義下,添加以下變量:
public GameObject followTarget;
public float moveSpeed;
followTarget是您希望相機遵循的內(nèi)容,moveSpeed是它應該移動的速度。 通過將這些作為公共變量創(chuàng)建,Unity將允許您在Unity編輯器本身中設(shè)置這些變量,因此您可以將followTarget設(shè)置為陸戰(zhàn)隊員,并將moveSpeed放在心臟的內(nèi)容中,您很快就會看到。
現(xiàn)在將以下內(nèi)容添加到Update():
if (followTarget != null)
{
transform.position = Vector3.Lerp(transform.position,
followTarget.transform.position, Time.deltaTime * moveSpeed);
}
此代碼檢查是否有可用的目標。如果沒有,相機不會跟隨。
接下來,調(diào)用Vector3.Lerp()來計算CameraMount的所需位置。
Lerp()有三個參數(shù):3D空間中的起始位置,3D空間中的結(jié)束位置,以及介于起始位置和結(jié)束位置之間的點的介于0和1之間的值。 Lerp()返回由最后一個值確定的起始位置和結(jié)束位置之間的3D空間中的點。
例如,如果最后一個值設(shè)置為0,則Lerp()將返回起始位置。如果最后一個值為1,則返回結(jié)束位置。如果最后一個值為0.5,則它返回起始位置和結(jié)束位置之間的一個點。
在這種情況下,您將提供相機安裝位置作為開始,將播放器位置作為結(jié)束。最后,將自上一幀速率以來的時間乘以速度乘數(shù),以獲得最后一個參數(shù)的合適值。實際上,這使得攝像機安裝位置平穩(wěn)地移動到玩家隨時間的位置。
保存您的代碼并返回Unity。在Hierarchy中選擇CameraMount,然后查看Inspector。您將看到兩個名為Follow Target和Move Speed的新Field。如前所述,這些是由Unity剛剛添加到腳本中的public變量自動派生的。這些變量需要一些值。
在層次結(jié)構(gòu)中仍然選中CameraMount的情況下,將SpaceMarine拖到Follow Target字段并將Move Speed設(shè)置為20。

玩下游戲看看發(fā)生了什么變化

陸戰(zhàn)隊員現(xiàn)在是一個真正的超級明星,配有個人攝制組。 當然,他無法轉(zhuǎn)身,他就像Kitty Pryde一樣穿過物體,但這些都是你現(xiàn)在無需解決的容易解決的問題。
注意:移動速度越大,相機支架移動到玩家的速度就越快。 越小,攝像機就越“滯后”陸戰(zhàn)隊員的位置,讓玩家“超前”攝像機。 嘗試將移動速度更改為較小的值,例如2,看看自己會發(fā)生什么!
Adding Gunplay
不幸的是,外交的精細部分在這場比賽的肉食對手身上失去了。 你最好給英雄一些火力,這樣他就可以在他非常輕松(可怕的)假期中保護自己。
首先,您需要創(chuàng)建一個子彈。 在“層次結(jié)構(gòu)”中,單擊“創(chuàng)建”按鈕。 從下拉列表中,選擇3D Object\Sphere以在Scene view視圖中創(chuàng)建球體。

把它命名為Projectile。 如果仍然選中它,請查看Inspector。 你會發(fā)現(xiàn)一堆新組件。

這三個新組件是:
- 1)
Mesh Filter是一個組件,包含有關(guān)模型網(wǎng)格的數(shù)據(jù)并將其傳遞給渲染器。 - 2) 網(wǎng)格渲染器
(Mesh Renderer)顯示網(wǎng)格。它包含許多關(guān)于照明的信息,例如投射和接收陰影。 - 3) 最后,你會注意到球體包含一個球體對撞機
(Sphere Collider)。該組件充當GameObject的邊界。
由于你希望子彈參與Unity的物理學,它需要一個Rigidbody。
幸運的是,你以前做過這件事。單擊Add Component按鈕,然后從Physics類別中選擇Rigidbody。確保取消選中Use Gravity。
由于隊員將燃燒大量射彈(projectile),因此將其從“層次結(jié)構(gòu)”拖動到項目瀏覽器中的“預制”文件夾。從層次結(jié)構(gòu)中刪除射彈,因為現(xiàn)在它不再需要它作為預制件。
此時,您需要創(chuàng)建一個腳本來啟動射彈。在項目瀏覽器中,選擇Scripts文件夾,然后單擊“創(chuàng)建”按鈕。選擇C#Script并將其命名為Gun。雙擊該文件以啟動代碼編輯器。
此文件需要在類定義下面的一些屬性。添加以下內(nèi)容:
public GameObject bulletPrefab;
public Transform launchPosition;
同樣,當您在腳本上創(chuàng)建公共變量時,Unity會在編輯器中公開這些變量。 您將bulletPrefab設(shè)置為剛剛創(chuàng)建的子彈預制件,然后將launchPosition設(shè)置為Space Marine槍管的位置。
接下來,添加以下方法:
void fireBullet()
{
// 1
GameObject bullet = Instantiate(bulletPrefab) as GameObject;
// 2
bullet.transform.position = launchPosition.position;
// 3
bullet.GetComponent<Rigidbody>().velocity =
transform.parent.forward * 100;
}
下面進行細分說明:
- 1)
Instantiate()是一種內(nèi)置方法,可為特定預制件創(chuàng)建GameObject實例。在這種情況下,這將基于子彈預制件創(chuàng)建一個子彈。由于Instantiate()返回一種Object類型,因此必須將結(jié)果強制轉(zhuǎn)換為GameObject。 - 2) 子彈的位置設(shè)置為發(fā)射器的位置 - 您將在短時間內(nèi)將發(fā)射器設(shè)置為槍管。
- 3) 由于子彈上附有剛體
(Rigidbody),因此您可以指定其速度以使子彈以恒定速率移動。方向由該腳本所附著的物體的變換決定 - 你很快就將它附著在隊員的身體上,確保子彈的行進方向與隊員相同。
保存并切換回Unity。在Hierarchy中,展開SpaceMarine GameObject并選擇BobbleMarine-Body GameObject。
在Inspector中,單擊Add Component按鈕并在組件列表底部附近,選擇Scripts。從腳本列表中選擇Gun。

你會看到你的Gun腳本組件已被添加到隊員的身體中。 您還會注意到有兩個新字段:Bullet Prefab和Launch Position。 聽起來很熟悉嗎?
單擊Bullet Prefab旁邊的圓圈。 在Select GameObject對話框中,單擊Assets選項卡。 從結(jié)果列表中選擇Projectile。 現(xiàn)在你加載了子彈,只需要設(shè)置發(fā)射位置。

在層次結(jié)構(gòu)中,按住PC上的Alt鍵或Mac上的Option,然后單擊BobbleMarine-Body旁邊的顯示三角形。 你會看到一個很大的子GameObjects列表。 尋找Gun。

選擇該GameObject并單擊Create按鈕。 選擇Create Empty Child并將其重命名為Launcher。 這個新的GameObject存在于槍管的中心,代表子彈產(chǎn)生的地方 - 如果你想調(diào)整外星怪物產(chǎn)卵的位置,可以隨意在場景編輯器中移動它。

保持所有GameObjects擴展并選擇BobbleMarine-Body,以便Inspector顯示所有組件。 將新的Launcher GameObject拖動到Gun組件的Launch Position字段中。
請注意,當您將GameObject添加到變換字段時,Unity會查找并引用附加的變換。
這是官方的! 隊員的槍被鎖定和裝載。 剩下的就是點火代碼。 謝天謝地,這很簡單。

切換回代碼編輯器并打開Gun.cs
當用戶按下鼠標按鈕時槍應該發(fā)射,當用戶釋放它時停止。
你可以簡單地檢查按鈕是否在Update()中按下并調(diào)用fireBullet()(如果是這樣),但是因為每幀都調(diào)用Update(),這意味著你的隊員每秒最多可以射擊60次! 我們的隊員可以快速射擊,但速度不快。
你需要的是你射擊子彈之間的輕微延遲。 為此,請將以下內(nèi)容添加到Update():
if (Input.GetMouseButtonDown(0))
{
if (!IsInvoking("fireBullet"))
{
InvokeRepeating("fireBullet", 0f, 0.1f);
}
}
首先,使用輸入管理器(Input Manager)檢查是否按下了鼠標左鍵。
注意:如果你想檢查鼠標右鍵,你會傳入
1,而對于鼠標中鍵,你會傳入2。
如果按住鼠標,則檢查是否正在調(diào)用fireBullet()。 如果沒有,則調(diào)用InvokeRepeating(),它會重復調(diào)用方法,直到您調(diào)用CancelInvoke()。
InvokeRepeating()需要方法名稱,開始時間和重復率。 InvokeRepeating()是MonoBehaviour的一種方法。
在那段代碼之后,添加以下內(nèi)容:
if (Input.GetMouseButtonUp(0))
{
CancelInvoke("fireBullet");
}
此代碼使得一旦用戶釋放鼠標按鈕,槍停止觸發(fā)。 保存你的工作并返回Unity,然后玩游戲。

按住鼠標按鈕。 你有幾天的子彈!
在這一點上,你應該對Unity感覺更舒服。 你有一個帶有武器的隊員。 您已經(jīng)學會了以下內(nèi)容:
- Components以及它們?nèi)绾螢?code>GameObjects提供行為。
- Scripting以及如何使用腳本創(chuàng)建自定義行為。
- Input Manager以及如何從代碼中訪問它。
- Game window以及如何測試游戲。
還有很多事要做。 你的可憐的隊員無法轉(zhuǎn)過身來看看他背后隱藏著什么。 與此同時,他沒有什么可擔心的,因為沒有外星人攻擊他!
后記
本篇主要講述了一款簡單射擊游戲示例,感興趣的給個贊或者關(guān)注~~~
