最近在研究Unity 3D,看了老外Marin Todorov寫的教程很詳細,就翻譯過來以便自己參考,翻譯不好的地方請多包涵。
這是使用Unity 游戲開發工具制作一個簡單的2.5D 游戲系列教程的第二部分。如果你沒有看到第一部分的話請先看。
在系列教程的第一部分,我們覆蓋了一些怎樣使用Unity的基礎性知識 和使用 C#寫一些腳本。我們創建了一個簡單的游戲,一個飛機可以來回飛行同時轟炸鯊魚,保護小魚!
在這個教程的第二部分也是最后一部分,我們將延長這個游戲添加一些收尾內容。我們將添加一個聲音效果和音樂,完善游戲邏輯,並為游戲添加多個場景!
如果你還沒有這個項目,請下載我們在上個教程留下的 project,並使用Unity打開它。如果它不能啟動和加載,確保點擊Scenes\LevelScene選項,讓它可見。
好了,讓我們學習更多有關Unity的知識,並完善這個游戲。
1. 添加iCandy到游戲中

你已經注意到 ,當炸彈擊中鯊魚時,它只是靜靜地消失,你會想:“那不是非常酷!”
好吧,我們要添加一個很酷的水下爆炸效果!
從菜單欄中選擇“GameObject/Create other/Particle System”,你會看到一個粒子系統出現在場景中,在“Hierarchy”面板中重命名這個Particle System”為 “Explosion”(爆炸),設置這個Explosion的position位置為[1, 1, 8].
現在你如果是一個粒子系統的專家——前往“Inspector”面板自己設置 ,如果你不是,只需要跟隨我們的指導是很容易的。覆蓋這些值到”Inspector“中:

這里最重要的屬性是“One shot”——當你檢查它時,系統將只會發送一次粒子 ——正如爆炸那樣。現在讓我們設置動畫值——只是嘗試更多或更少的顏色相匹配(如果你不做,也並不重要):
 
這里最重要的屬性是“Autodestruct”(自毀)——當選中這個粒子系統時,當沒有更多活動的粒子時將會把自己從場景中移出去。這正是我們想要的——它就像一個垃圾收集器。
現在你有一個漂亮的小規模爆炸,你需要做一個像之前做炸彈的一樣——做一個預制,在需要它的時候實例化,當它在場景中完成任務時讓它自動銷毀。
在“Project”面板中“Prefabs”文件上右鍵單擊,選擇 “Create/Prefab”,重命名為 “ExplosionPrefab”.在“Hierarchy”面板中拖拽 “Explosion”對象到這個新建的“ExplosionPrefab”文件上。在“Hierarchy”面板中右鍵單擊 “Explosion”並選擇刪除。
在"Project"面板中右鍵單擊,選擇“Sync MonoDevelop Project”來打開MonoDevelop。打開BombClass.cs文件,並在里面添加如下代碼:
//right under definition of "ySpeed" public GameObject explosionPrefab; //inside OnTriggerEnter, right after Destroy(this.gameObject) Instantiate(explosionPrefab, transform.position, Quaternion.identity);
現在切換回Unity並在“Project”面板中選中“BombPrefab”——在“Inspector”面板中你可以看到新的屬性 “ExplosionPrefab”。只需要拖拽在“Project”面板中的“ExplosionPrefab”文件到這個新的屬性文件上,你就設置好了。

好了——點擊Play按鈕,觀看你命中鯊魚的爆炸效果。
 
2.添加earCandy到游戲中
不要告訴Steve,但是對於我們iCandy不夠的,我們也需要一些earCandy!
我們怎么能只有一個游戲而沒有背景音樂?我們要拜訪另一個偉大的人——Kevin Macleod。他是一個偉大的電影和游戲音樂作曲家,他的作品有在 CC license許可下。所以你要使用他的東西不要忘了署名。
打開鏈接:http://incompetech.com/m/c/royalty-free/index.html?keywords=the%20cannery
一旦你到達這個頁面時,下載“The Cannery”文件到你的硬盤上,並拖拽下載好的“The Cannery.mp3″文件到你“Project”面板的 “Audio”文件夾下。
我們想把音樂全時段的循環播放——但是我們應該把它附加到那個對象上呢?
好吧,讓我們把它附加到camera相機上!這個camera也是一個游戲對象,並可以有其他附加組件。
從“Project”面板中把“The Cannery”拖拽到“Hierarchy”面板中的“Main Camera”上。 選中“Hierarchy”面板中的“Main Camera”,並在“Inspector”面板中找到 “Audio Source”選項 ——勾選住“Loop”選項框並設置Volume值為“0.20”.
就是這樣簡單——運行這個場景並享受這個新的背景音樂吧!
3.使用Unity 創建一個GUI
讓我們進入一個新的領域——GUI。Unity為你提供一些標准的labels和buttons,但是這些都不是Unity強大的功能。然而,我們需要一個label來顯示當前的得分;所以首先我們需要實現得分的邏輯。
切換回MonoDevelop。 打開PlayerClass.cs文件並添加一個新的屬性:
public static int score = 0;
啊哈!又有了新的東西—— “static”。當類被加載和時這個屬性將被創建,不管是否有這個類的實例。此外,這個屬性可以被其他類訪問——這就是為什么我們要保持這個得分計數為靜態類型的原因。
接下來添加更新得分的方法(現在沒有太大的意義,但只管先創建它)——看比分屬性是如何通過類名訪問:
public void updateScoreBy(int deltaScore) { PlayerClass.score += deltaScore;
}
再添加一個新方法到 PlayerClass——這將會在屏幕上繪制得分計數:
void OnGUI() { GUIStyle style = new GUIStyle(); style.fontSize = 20; GUI.Label(new Rect(10,10,100,20), "Score:"+PlayerClass.score, style);
);
}
"OnGUI"此事件在GUI layer(圖形用戶界面層)每一幀上被調用。
GUIStyle是一個類,它類似一個CSS類——所以你可以使用fontSize,marginLeft這樣的你所熟悉的CSS方法,否則現在只保留字體大小。GUI.Label()是個擁有3個參數的方法:一個矩形的Label,繪制的字符串,和text風格。這就是全部了。
剩下的唯一的任務是:當我們有命中或沒命中時更新比分。 打開BombClass.cs文件,並做如下代碼修改:
//add a new property public PlayerClass player; //replace the existing OnTriggerMethod with void OnTriggerEnter(Collider obj) { if (obj.gameObject.name == "Shark") { //reset shark obj.gameObject.transform.rotation = Quaternion.identity; obj.gameObject.transform.position = new Vector3(20f, -3f, 8f); player.updateScoreBy(+1); Destroy(gameObject); Instantiate(explosionPrefab, transform.position, Quaternion.identity); } if (obj.gameObject.name == "ClownFish") { //reset fish obj.gameObject.transform.rotation = Quaternion.identity; obj.gameObject.transform.position = new Vector3(-20f, -1f, 8f); player.updateScoreBy(-1); Destroy(gameObject); Instantiate(explosionPrefab, transform.position, Quaternion.identity); }
}
這跟我們以前的非常相似, 但我們有了一個新的屬性叫做“player”,並且當我們需要更新分數時我們只需要調用player.updateScoreBy()。
也為了使游戲更加有趣,如果你打的是鯊魚你將得到一個點,如果你打的是小魚,那么你將失去一個點。下載呢,塑造一場艱難的比賽!
最后一件事——設置這個player(玩家)屬性上的炸彈。現在我們不能像之前那樣創建,因為炸彈是動態創建的,但幸運的是炸彈是由玩家自己創建,這樣他可以在創建時設置這個玩家屬性。
讓我們開始做——打開PlayerClass.cs文件並在這一行“bombObject.transform.position = this.gameObject.transform.position;”下方添加如下代碼:
BombClass bomb = (BombClass)bombObject.GetComponent("BombClass"); bomb.player = this;
這又有了新的東西了!讓我們分析下:bombObject是一個GameObject對象的實例化(實例化返回),所以我們稱之為“GetComponent”,並且這樣我們可以訪問所有連接的游戲對象組件——結果我們映射到一個BombClass——所以最后我們得到連接到游戲對象的C#類的引用。接下來,我們只要設置“player”屬性(PlayerClass 的實例)。
運行這個場景,你將會看到分數顯示!

4.Unity 對象和組件
到這個地步,你對Untiy的游戲對象模型被引用已經有了足夠的練習使用。更好地了解你實際上是在做什么,對不對?讓我們做一個非常短的復習來看卡游戲中的涉及對象和組件是如何連接的。
在“Inspector”面板中我們所看到的所有選項條目——這些事游戲對象中比較重視的組件。一個空的對象只有它的 transform選項條目——position, rotation, scale.這是所有的——一切附加組件。
- Transform: provides position, rotation, and scale, as described above.(提供位置,旋轉和縮放,如上所述。)
 
- Mesh Filter: provides the geometry of the visible object.(提供可視對象的幾何形狀。)
 
- Mesh Renderer: renders the geometry.(呈現幾何。)
 
- Rigidbody: handles physics.(處理物理。)
 
- Audio Source: plays audio.(播放音頻。)
 
- Script: can programmatically update the object.(可以通過編程更新對象。)
 
這些只是小數屬性可以附加到一個對象上。為了更好的理解,讓我們看卡這張圖片:
 
因此,腳本組件采用點視圖方式。它會看起來更清楚一些,為什么我們不得不調用它:
Destroy(this.gameObject);
為了銷毀一切跟對象有關的實例。通過游戲對象的屬性我們可以訪問所有其他組件,所以我們可以physics物理化或調整音量,等等。
5.添加更多的場景
現在我們的游戲是越來越好了,但是沒有方式顯示輸和贏!
所以讓我們添加一個“you win”的場景,當玩家做出3點以上的成績時。
從菜單欄中選擇“File/New Scene”,然后再次從菜單欄中選擇“File/Save Scen”,彈出框中選擇文件夾“【你的項目目錄】/Assets/Scenes”,沒有Scenes文件夾就創建一個,並以“WinScene”文件名保存。
在“Hierarchy”面板中選中“Main Camera”並設置:Position [0, 0, 0],Projectio為“Orthographic”, Size 為 “10″, Near 為 “0.5″ and Far 為 “22″。從菜單欄中選擇“GameObject/Create Other/Directional Light”並在“Inspector”面板中設置:Position [0, 0, 0].
我們想要在場景中放一個平面(像在我們游戲中的背景),並放一個圖片在它上面叫“you win”,所以讓我們像在第一部分中所做一樣:從菜單欄中選擇“GameObject/Create Other/Plane”並在“Inspector”面板中設置:Position [0, 0, 8], Rotation 為 [90, 180, 0], Scale 為 [3, 1, 2].
下一步下載並保存 Vicki Wenderlich所做的這個圖片到你的硬盤上,瀏覽如下:

拖拽下載的“gameover_youwin.png”到“Project”面板中的“Textures”文件夾中。這個紋理被導入后看起來有點臟——這是因為壓縮的原因,只需要在“Project”面板中選中 “gameover_youwin”紋理,然后在“Inspector”面板中找到 “Format”並改變它的值為 “16bits”,並點擊“Apply”。現在把“Project”面板中的“gameover_youwin”拖拽到“Hierarchy”面板中的“Plane”上。在你的“Game”面板中你應該看到“You win”——Vicki所繪制的這個邪惡的鯊魚漂浮起來。
我們需要讓它活動起來——當場景被點擊時,游戲應該重新啟動:在“Project”面板中的“Class”文件夾下右鍵單擊,並選擇“Create/C Sharp Script”,然后重名為“GameOverClass”。在"Project"面板中右鍵單擊並選擇“Sync MonoDevelop Project”。在MonoDevelop中打開新建的 GameOverClass.cs文件,並替換如下代碼:
using UnityEngine; using System.Collections; public class GameOverClass : MonoBehaviour { // Update is called once per frame void Update () { if (Input.anyKeyDown) { PlayerClass.score = 0; Application.LoadLevel("LevelScene"); } }
}
當玩家點擊這個屏幕時候,比分重置和重新加載游戲場景。Application.LoadLevel()只需要加載場景的名字——很容易。
切換回Unity:從“Project”面板中的“Class”文件夾下拖拽 “GameOverClass”腳本文件到“Main Camera”上。
現在在項目中包括這個場景下 選擇 “File/Build Settings”,並在彈出框中點擊 “Add current”按鈕,關掉框框。你已經添加這個場景到這個項目的建設中。
然我們也快速添加“You loose”場景!像上次一樣,制作一個“New scene”,然后保存這個新場景為“LooseScene”到這個“Scenes”文件夾下。
 在“Hierarchy”面板中選中 “Main Camera”並設置: Position [0, 0, 0], Projection to “Orthographic”, Size to “10″, Near to “0.5″ and Far to “22″。從菜單欄中選擇“GameObject/Create Other/Directional Light”,並在"Inspector"面板中設置:Position [0, 0, 0]。從菜單欄中選擇“GameObject/Create Other/Plane”,並在"Inspector"面板中設置: Position [0, 0, 8], Rotation to [90, 180, 0], Scale to [3, 1, 2]。
下載這個“You Lose”圖片保存在你的硬盤上面,預覽如下:

采取以下步驟包裝這個場景:
1.拖拽下載的“gameover_youlose.png”到“Project”面板中的“Textures”文件夾下。
2.在“Project”面板中選中 “gameover_youlose”紋理,然后在“Inspector”面板中找到“Format”改變它為“16bits”,並點擊 “Apply”。
3.從“Project”面板中拖拽 “gameover_youlose”文件到“Hierarchy”面板中的“Plane”上。
4.從“Project”面板中的“Class”文件夾下拖拽“GameOverClass”文件到這個“Main Camera”。
5.從菜單欄選擇“File/Build Settings”,在彈出框中,點擊“File/Build Settings”按鈕,關掉彈出框。
這里——你有3個場景,但你需要把它們聯系起來!
進入到這個LevelScene場景——通過雙擊“Project”面板中的 “LevelScene”。切換到MonoDevelop並打開PlayerClass.cs文件。我們要去修改這個updateScoreBy方法來檢測你是否贏得超過3點還是在負3點以下。
//replace the updateScoreBy method with this code public void updateScoreBy(int deltaScore) { PlayerClass.score += deltaScore; if (PlayerClass.score>3) { Application.LoadLevel("WinScene"); } else if (PlayerClass.score<-3) { Application.LoadLevel("LooseScene");
}
}
現在你的場景工作流程被設置。你可以在Unity中點擊Play按鈕運行游戲。其實——你為什么不點擊“File/Build&Run”,當Xcode彈出框——點擊“Run”,也就嘗試在您的iPhone上運行游戲。
6.展望2.5D——最后
是時候了,讓你在本系列教程的第二部分看你一直期待的2.5D技術!
我將提前爆料一個秘密——我打算把它幾乎為3D展示,為您的開發增添樂趣!
截止到現在,我們已經設置這個 cameras’ projection(攝像機的投影)為“Orthographic”(正面),這讓場景看起來像一個普通的2D游戲—到此為止!
在你的LevelScene場景中選中 “Main Camera”,並在“Inspector”面板中改變這個Projection為“Perspective”,和 “Field of View”為“100″(以Perspective的角度看).好了,點擊這個Play按鈕,在2.5D下觀看你的游戲。是不是很酷呢?

但是我們不能止步於此。
這有個計划——使游戲變得更加困難寫,並演示如何旋轉和移動攝像機,每一次的得分增加,我們將按鈕圓弧路徑移動攝像機,並改變它的角度。這樣你越在游戲中進步,你將不得從怪異的角度看目標和嘗試轟炸鯊魚!
切換回MonoDevelop,並對 PlayerClass.cs文件做如下更改:
//add the properties public GameObject mainCamera; public GameObject gameBackground; public float nextZ = 0; //at the end of the updateScoreBy method if (PlayerClass.score>0) { nextZ = PlayerClass.score*2.5f; } //at the end of the Update method if (nextZ > mainCamera.transform.position.z) { mainCamera.gameObject.transform.Translate( 3* Mathf.Sin(transform.position.z/2 ) * Time.deltaTime, 0, -Mathf.Sin(transform.position.z /2 ) * Time.deltaTime *0.3f ); mainCamera.gameObject.transform.RotateAroundLocal( Vector3.up, Time.deltaTime*0.1f ); gameBackground.gameObject.transform.RotateAroundLocal( Vector3.up, Time.deltaTime*0.1f );
}
好吧——大量的代碼,但是這正是我們需要的。讓我們一點一點地分析它:
首先,我們生命屬性來引用Main Camera和Background plane(平面)。我們將移動和旋轉攝像頭,我們也要將背景旋轉。
這個攝像機從它當前Z軸為0的位置移動到朝着background 7.2Z的位置。所以每次玩家得分,這個nextZ被設置為2.5,然后5.0,然后7.5——通過這些值Main Camera轉換到用sin函數的圓弧狀的東西。
所有的數學函數通過Mathf類——正如這個sin函數為 Mathf.Sin()。所以我們旋轉攝像機使用transform.RotateAroundLocal,我傳遞一個值(Vector3.up)繞軸,通過角度旋轉。我們使攝像機和背景一起旋轉,這樣攝像機始終面對着背景(即用不完的屏幕背景)。
更重要的事情——讓我們連接新的公共屬性。切換回Unity,在“Hierarchy”面板中選中“Player”對象。從“Hierarchy”面板中拖拽 “Main Camera”到“Inspector”面板中的新的 “Main Camera”屬性上;從“Hierarchy”面板中拖拽“Background”對象到“Inspector”面板中的新的 “Game Background”屬性上

恭喜,你終於完成了!點擊“File\Build and Run”,run the finished game on your iPhone.以怪異的角度轟炸鯊魚吧!

7.Unity調試
我想不免會觸及一些話題,因為當你自己開發時,你會碰上麻煩,你需要調試你的游戲,incident,一些簡單的事情要牢記:
1.不要忘記在toolbar工具欄上有一個暫停按鈕,所以你如果需要停止執行游戲,並檢查所有對象的屬性——只需要點擊Pause按鈕,然后瀏覽你周圍的廠家,在“Inspector”面板中查看各種屬性值。
2.如果你不確定你的方法是否觸發了,在控制台打印一條消息(類似在Xcode中)。使用:Debug.Log(“message”); 將消息打印到控制台。你可以選擇菜單欄“Window/Console”,來調出控制台窗口。
3.養成這種習慣:當你在MonoDevelop完成編碼時,你切換回Unity看一看Unity的狀態欄(在應用窗口的底部)——如果你寫了錯誤的代碼,將不會被驗證,你會得到有紅色的錯誤消息,你點擊這些錯誤消息就能馬上帶你回到MonoDevelop。
4.如果你的對象不動——三重檢查你的script腳本文件是否連接到你的對象上。
5.當你運行你的游戲時,你可以改變在“Inspector”面板中的值,只管嘗試不同的值。當你暫停游戲時:NB在“Inspector”面板中的所有值都被重置到你運行游戲之前的數據。因此,如果你忘了停止游戲和你進行的更改,它們會丟失,所以請務必完成測試后停止游戲,然后繼續開發。
源代碼如下:sample project
如果你想學習更多有關Unity的知識請訪問它們的論壇網站www.unity3D.com/support/.也可以看下Unity C# Reference.
如需轉載,請注明翻譯出處 http://www.cnblogs.com/jiangshiyong/p/3150991.html
