How to make a Video Game in Unity

How to make a Video Game in Unity 的課程筆記。

1. 基礎

  • Scene 視圖,滾動鼠標中鍵縮放,opt+左鍵以視圖中心為軸心旋轉。
  • Hierarchy 視圖中的元素
  • Inspector 放 components,使對象做不同的事
  • Assets 資源,拖放到視圖中,會在 Hierarchy 中顯示
  • 左上角 5 個 icon 對應 q, w, e, r, t 快捷鍵,可以移動畫幅,移動對象,旋轉對象,變形對象,縮放對象
  • Game 視圖,按 shift+space 切換全屏與小窗口
  • Command+P 運行游戲

創建項目

  1. 創建 cube,Scene 中按 F 會聚焦到所選擇的對象。
  2. Inspector > Transform 中點右鍵 reset,會把該對象以原始大小重置到視圖中央。
  3. Game 視圖中以 Camera 的角度觀察。
  4. 設置地面:修改 cube 的 scale,移動到 camera 前一點的位置。改名為 Ground
  5. 創建 Player:再創建一個 cube,reset,拖到 ground 之上,改名 Player.
  6. 給 Player 上色:Assets 中新建 Material,名為 PlayerMat,Albede 改為紅色,拖到 Player 上。
  7. 使 Player 有物理特性:Add Component > Physics > Rigidbody。
  8. 是什么使對象有不同的特性呢?答案是 components。Transform 每個對象都有的屬性;Mesh Renderer 渲染對象到視圖;Box Collider 碰撞屬性。每個物理對象都需要 Box Collider 和 Rigidbody。Cube(Mesh Filter) 選擇不同的形狀。
  9. 如果改成球體,box collider 右鍵 remove component,然后 add component > Sphere Collider。
  10. 改變背景色:選擇 mainc camera > Inspector > Camera > Clear Flag > Solid Color, background 選擇淺灰色
  11. 保存 scene,在 unity 中,scene 就是 level。

2. 編程

  1. 選擇 Player,add component > script,輸入 PlayerMovement

  2. 可以拖放 script 到某個對象上,使它產生作用。

  3. Unity 5.5.2 會自動產生這兩行,刪除掉:

     using System.Collections;
     using System.Collections.Generic;
    
  4. Start () 在開始執行,Update () 每一幀執行。我們要訪問 rigidbody

     public Rigidbody rb;
    

    然后在 inspector 面板中,把 Rigidbody 這個 component 拖到 rb 變量中,以便在代碼中引用。

  5. 加驅動力給 Player,為了避免計算快的計算機比慢的運動速度不一致,將參數乘以 Time.deltaTime

     rb.AddForce(0, 0, 2000 * Time.deltaTime)
    
  6. 放在 FixedUpdate() 中,當對象和別的物體碰撞的時候會更順滑一些。

3. 移動

  1. 不讓 Player 滾動,只需要滑動,可以勾選 Constraints > Freeze Rotation > x,不過我們希望碰撞的時候可以滾動,所以不要這樣設置。

  2. 導致 Player 滾動的是摩擦力,Assets > 右鍵 > Create > Physic Material,命名為 Slippery,Inspector 中 Dynamic Friction 和 Static Friction 都設為 0,拖放到 Ground 上。

  3. 要在 inspector 中修改速度,創建一個速度變量:

     public float forwardForce = 2000f;
    

    修改

     rb.AddForce (0, 0, forwardForce * Time.deltaTime);
    
  4. 判斷用戶輸入,左右移動 Player

     public float sidewaysForce = 500f;
     
     if ( Input.GetKey("d") ) {
             rb.AddForce (sidewaysForce * Time.deltaTime, 0, 0);
         }
         if ( Input.GetKey("a") ) {
             rb.AddForce (-sidewaysForce * Time.deltaTime, 0, 0);
         }   
    

4. 攝像頭

  1. Camera 跟隨 Player: 可以把 Main Camera 拖到 Player 下,使它成為 Player 的子對象,不過當 Player 碰撞滾動的時候 Camera 也跟著滾,太詭異,所以我們將用代碼來實現。

  2. 給 Main Camera 添加 script —— FollowPlayer

     using UnityEngine;
     
     public class FollowPlayer : MonoBehaviour {
     
         //只需要用到 transform,所以不需要引用到 GameObject
         public Transform player;
         //使得在 Inspector 中可以設置三個參數 x = 0, y = 1, z = -5
         //橫向x不變,縱向 y 向上一點,沿著 z 軸跑的,放后面一點
         public Vector3 offset;
         
         // Update is called once per frame
         void Update () {
             //使 Camera 在 Player 的后上方
             //不必 x, y, z 分別計算,兩個屬性都有這 3 個參數,所以可以直接相加
             transform.position = player.position + offset;
         }
     }
    
  3. 這樣當碰撞的時候 Player 在滾動,Camera 仍然在它后方穩定觀察。

5. 碰撞

  1. 為 Player 創建 PlayerCollision.cs

     using UnityEngine;
     
     public class PlayerCollision : MonoBehaviour {
     
         //引用另外一個 script
         public PlayerMovement movement;
         
         //碰撞的時候會自動呼叫這個方法
         void OnCollisionEnter (Collision collisonInfo) {
             if (collisonInfo.collider.tag == "Obstacle") {
                 //發生碰撞時,使驅動 Player 滑動的 script 失效
                 movement.enabled = false
             }
         }
     }
    
  2. 在 inspector 中把 PlayerMovement 拖到 PlayerCollision 的接口中。

6. 游戲設置

  1. 把 hierachy 中的 Obstacle 拖到 Assets 面板中,這個對象就變成一個 prefab,這個預制件可以在游戲中重復使用,拖放多個 prefab 到 Scene 中,修改 prefab 會使所有 prefab 都發生改變,也可以單獨修改某個 Obstacle,修改某個對象后點擊 inspector 中的 apply 會使當前修改應用到所有 prefab 對象。

  2. 通常我們會讓 obstacle 向 player 移動,造成前進的視覺,但是這個 demo 中我們讓 player 移動。

  3. 延長 Ground:Inspector 中設置 Transform.Position.z: 4980, Scale.z: 10000

  4. Scene 右上角,點擊 y 軸,這樣視角就改成從頂部往下看,點擊中心的方塊,會取消掉透視效果,這樣我們可以在 2d 效果中設置游戲障礙物。

  5. Inspector > Layers > Edit Layers, 添加 Environment Layer;選擇 Ground,Inspector > Layer > Environment;下拉 Layers,點擊 Environment 右側鎖頭鎖住。這樣我們再也不能選中視圖中的 Ground 了。這樣便于設置 ground 上的障礙物。

  6. 選擇障礙物,如果點擊綠色方框,那么只會沿著 z 和 x 軸移動。

  7. 設置吸附:菜單 Edit > Snap Settings...,設置 2, 2, 2, 按住 Command 再拖動的障礙物的時候,它會 2 個單位移動每一步。

  8. 復制多個障礙物,布滿 ground。

  9. Player 響應方向改變有點遲鈍,rb.AddForce 方法的幾個參數重,首先給 x 加力度,然后是 y, 然后是 z,最后是 Force Mode,ForceMode 默認是 forced,它根據重量添加一個持續的壓力給 rigidbody,我們想要的是當速率改變時,完全忽略這個物體的重量。所以添加 ForceMode.VelocityChange 參數。

     if ( Input.GetKey("d") ) {
                 rb.AddForce (sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
             }
             if ( Input.GetKey("a") ) {
                 rb.AddForce (-sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
             }   
    
  10. 看起來響應比較及時了,為了讓運動看起來更有逼真,設置 drag 屬性,drag 意味著空氣阻力,drag 越大,我們的 Player 越容易被空氣攔住停止,此外我們還要增加推力,以便保持運動速度。drag:1, forwardForce: 4000

  11. 障礙物看起來好像突然冒出來一樣,我們要讓它們漸漸出現。菜單 window > lighting > 勾選 Fog > Fog Color 吸附背景色 > Density: 0.02

  12. 有時候 Player 會穿越障礙物,為了增加更精確的碰撞感知,Player 和 Obstacle 的 Rigidbody > Collision Detection 都設置為 continuous

  13. Edit > Project Settings > Time > Fixed Timestep : 0.02,這樣 unity 會更頻繁地檢查物理狀況,減少錯過的碰撞。

  14. 提高 Player 的推力 8000

7. UI

  1. Hierachy 面板,右鍵 > UI > Text

  2. Scene 點擊頂部 2d,點擊 cavas,點擊 scene,敲F,聚焦到 UI 視圖

  3. 設置 text 位置,字體大小,外框大小,按 option 鍵從中間縮放,Horizontal Overflow 設為 overflow 意味著如果文字超出也能顯示。

  4. 選擇 canvas,設置 UI Scale Mode: Scale With Screen Size, Match Height

  5. 下載 roboto 字體(select后點小窗點download)。解壓。拖到 assets 中。選擇 text,選擇字體。

  6. 給 text 添加 script

     using UnityEngine;
     using UnityEngine.UI; //設置 text 需要引入 UI
     
     public class Score : MonoBehaviour {
         //只需要位置信息,所以不引用 GameObject 
         public Transform player;
         //引用 Label
         public Text scoreText;
     
         // Update is called once per frame
         void Update () {
             //轉換浮點數為 string  并且只保留整數
             scoreText.text = player.position.z.ToString("0");
         }
     }
    
  7. 選擇 canvas,Inspector 勾選 Pixel Perfet,這樣字體會渲染得更銳利。

8. 游戲結束

  1. 創建 GameObject,reset transform。重命名為 GameManager。給它添加 script: GameManager,它將負責管理游戲狀態。比如更新游戲分數,切換菜單,切換游戲層級等等。我們要做的是失敗后重置游戲。

  2. Player 碰撞的時候要呼叫 GameManager,如果直接引用它,有時我們需要讓 Player 死掉,這時 它所綁定的 GameManager 也就不存在了。因此我們不用引用變量的方法。

  3. 把 Player 拖到 Assets 面板,變成 Prefab。 Main Camera 和 text 所引用的 Player 都要重新設置。

  4. 當需要的時候我們搜索這個 GameManager。GetComponent 和 FindObjectOfType 這兩個方法都類似。

     using UnityEngine;
     using UnityEngine.SceneManagement;
     
     public class GameManager : MonoBehaviour {
         //避免重復呼叫 EndGame()
         bool gameHasEnded = false;
     
         public float restartDelay = 1f;
     
         public void EndGame(){
             if(gameHasEnded == false){
                 gameHasEnded = true;
                 //延遲執行,第一個參數是呼叫的方法名,第二個參數是延遲的秒數
                 Invoke ("Restart", restartDelay);
             }
         }
     
         void Restart(){
             //重載當前 scene
             SceneManager.LoadScene (SceneManager.GetActiveScene ().name);
         }
     }
    
  5. 修改 PlayerCollison.cs

     //movement.enabled = false;
                 GetComponent<PlayerMovement>().enabled = false;
                 //找到 GameManager
                 FindObjectOfType<GameManager> ().EndGame();
    
  6. 當 Player 掉下 Gound 時呼叫 EndGame。修改 PlayerMovement.cs

     if (rb.position.y < -1f){
                 FindObjectOfType<GameManager> ().EndGame ();
             }
    
  7. 修正 lighting:Window > Lighting,去掉底部 auto 選項。auto 表示 unity 自動檢查光線,當重載 scene 的時候,unity 時間去計算光線,它會使畫面非常亮,所以要去掉。點 build。

  8. 如果多于一個 scene,我們還要 File > Build settings,把 Scene 拖進去。build and run

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,436評論 2 378

推薦閱讀更多精彩內容