How to make a Video Game in Unity

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

1. 基礎(chǔ)

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

創(chuàng)建項目

  1. 創(chuàng)建 cube,Scene 中按 F 會聚焦到所選擇的對象。
  2. Inspector > Transform 中點右鍵 reset,會把該對象以原始大小重置到視圖中央。
  3. Game 視圖中以 Camera 的角度觀察。
  4. 設(shè)置地面:修改 cube 的 scale,移動到 camera 前一點的位置。改名為 Ground
  5. 創(chuàng)建 Player:再創(chuàng)建一個 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 到某個對象上,使它產(chǎn)生作用。

  3. Unity 5.5.2 會自動產(chǎn)生這兩行,刪除掉:

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

     public Rigidbody rb;
    

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

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

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

3. 移動

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

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

  3. 要在 inspector 中修改速度,創(chuàng)建一個速度變量:

     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 的子對象,不過當(dāng) Player 碰撞滾動的時候 Camera 也跟著滾,太詭異,所以我們將用代碼來實現(xiàn)。

  2. 給 Main Camera 添加 script —— FollowPlayer

     using UnityEngine;
     
     public class FollowPlayer : MonoBehaviour {
     
         //只需要用到 transform,所以不需要引用到 GameObject
         public Transform player;
         //使得在 Inspector 中可以設(shè)置三個參數(shù) 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 個參數(shù),所以可以直接相加
             transform.position = player.position + offset;
         }
     }
    
  3. 這樣當(dāng)碰撞的時候 Player 在滾動,Camera 仍然在它后方穩(wěn)定觀察。

5. 碰撞

  1. 為 Player 創(chuàng)建 PlayerCollision.cs

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

6. 游戲設(shè)置

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

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

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

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

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

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

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

  8. 復(fù)制多個障礙物,布滿 ground。

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

     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. 看起來響應(yīng)比較及時了,為了讓運動看起來更有逼真,設(shè)置 drag 屬性,drag 意味著空氣阻力,drag 越大,我們的 Player 越容易被空氣攔住停止,此外我們還要增加推力,以便保持運動速度。drag:1, forwardForce: 4000

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

  12. 有時候 Player 會穿越障礙物,為了增加更精確的碰撞感知,Player 和 Obstacle 的 Rigidbody > Collision Detection 都設(shè)置為 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. 設(shè)置 text 位置,字體大小,外框大小,按 option 鍵從中間縮放,Horizontal Overflow 設(shè)為 overflow 意味著如果文字超出也能顯示。

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

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

  6. 給 text 添加 script

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

8. 游戲結(jié)束

  1. 創(chuàng)建 GameObject,reset transform。重命名為 GameManager。給它添加 script: GameManager,它將負(fù)責(zé)管理游戲狀態(tài)。比如更新游戲分?jǐn)?shù),切換菜單,切換游戲?qū)蛹壍鹊取N覀円龅氖鞘『笾刂糜螒颉?/p>

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

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

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

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

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

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

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容