Unity入門教程(下)

1、概要

在 Unity入門教程(上) 中咱們建立了一個遊戲項目,而且建立了玩家角色和小球這些遊戲對象,還經過添加遊戲腳本實現了小方塊的彈跳。雖然功能比較簡單,可是完整地表現了使用Unity開發遊戲的大致流程。html

爲了讓這個遊戲變得更加有趣,下面咱們要進一步完善玩家角色和小球的動做。編程

 

2、讓小球飛起來(物理運動和速度)

目前小球是靜止在空中的,下面咱們來嘗試讓它朝玩家角色飛去。ide

爲了令小球可以模擬物理運動,須要添加Rigidbody組件。同時還須要建立一個Ball的腳本。此操做在Unity入門教程(上)中的步驟十和步驟十一。工具

 

添加了Ball腳本之後,咱們要對Start方法做以下修改學習

    void Start () {
        this.GetComponent<Rigidbody>().velocity = new Vector3(-8.0f, 8.0f, 0.0f); //設置向左上方的速度
    }

 

遊戲開始後,小球將向畫面左側飛去this

 

3、建立大量小球(預設遊戲對象)

爲了可以隨時建立出小球對象,首先須要對小球對象進行預設。spa

1,請將層級視圖中的Ball項文本拖拽到項目視圖中

項目視圖中將出現Ball項。同時,層級視圖中的Ball項文本將會變爲藍色。3d

 

2,將項目視圖中的Ball預設拖拽到場景視圖中

能夠看到場景中會多出一個小球對象。code

預設了遊戲對象後,咱們就可以很是容易地建立出多個一樣的物體。htm

 

3,將Player和Floor遊戲對象也作成預設

 

4、整理項目視圖

1,用文件夾將這些項目歸類整理

在項目視圖左上角的菜單中點擊Create→Folder後,項目視圖中將生成一個文件夾,將名字改成Prefabs。

 

2,將預設Ball Prefab拖拽到Prefabs文件夾下

點擊Prefabs文件夾,能夠看到剛纔移動的Ball預設。接着把Player預設和Floor預設也移動到Prefabs文件夾下。

 

3,採用一樣的方式建立Scenes、Scripts、Materials文件夾,並把各項目放到相應的文件夾下

注意在建立前務必先點擊項目視圖左側的Assets圖標以確保當前文件夾回到Assets。

 

5、發射小球(經過腳本建立遊戲對象)

1,在窗口頂部菜單中依次點擊GameObject→Create Empty

因爲該遊戲對象被用做發射臺,所以命名爲Launcher

 

2,對遊戲對象Launcher進行預設

 

3,建立Launcher腳本

 

4,將Launcher腳本添加到Launcher預設中去(另一種方法)

(1)在項目視圖中切換到Prefabs文件夾,點擊選中Launcher預設。此時檢視面板上將顯示Launcher的相關信息,而後點擊最下方的Add Component按鈕

 

 (2)在標題爲Component的下拉菜單中點擊最下方的Script項。點擊後菜單將向左移動,顯示出全部建立好的腳本。找到Launcher腳本並點擊。

小結:如今咱們已經知道在檢視面板中也能夠添加組件,除此以外,還可使用窗口頂部菜單或者直接拖拽。

 

5,編輯Launcher腳本

除了Update方法有變更以外,還增長了ballPrefab變量。

Instantiate是經過預設生成遊戲對象實例的方法。不過腳本中並無對ballPrefab變量進行初始化的代碼,因此在遊戲運行前必須先在檢視面板中對ballPrefab變量賦予預設對象值。

public class Launcher : MonoBehaviour {
    public GameObject ballPrefab;  //小球預設
    // Use this for initialization
    void Start () {
        
    }
    
    // Update is called once per frame
    void Update () {
        if (Input.GetMouseButtonDown(1))  //點擊鼠標右鍵後觸發
        {
            Instantiate(this.ballPrefab);  //建立ballPrefab的實例
        }
    }
}

 

從項目視圖中選擇Launcher預設。能夠看到在檢視面板中的Launcher(Script)標籤下顯示有Ball Prefab項。腳本代碼中聲明的全部public成員變量都將在這裏列出。

往類中新添加的變量默認表示爲None(GameObject),意味着該變量還未被賦值。請將項目視圖中的Ball預設拖拽到這裏(鼠標左鍵按着不要鬆手)。

 

6,運行遊戲

每次單擊鼠標右鍵時,都會射出一個小球。

這裏,爲了和預設對象分開,咱們把腳本中經過Instantiate方法生成的遊戲對象稱爲實例,把產生實例的過程稱爲實例化。

 

6、刪除畫面外的小球(經過腳本刪除遊戲對象)

咱們的遊戲如今出現了一個Bug:發射出去的小球永遠不會消失。

遊戲運行時由腳本動態生成的遊戲對象也會被顯示在層級地圖中。每點擊一次鼠標,層級視圖中都會增長一個Ball(Clone)遊戲對象。所以即便小球已經跑出遊戲畫面以外,這些遊戲對象也並未消失。

跑出畫面以外的小球不會再回到畫面中,因此徹底能夠刪除。

在腳本Ball.cs中添加OnBecameInvisible方法,該方法能夠被添加到Ball類定義範圍內的任意位置。

public class Ball : MonoBehaviour {
    //添加:遊戲對象跑出畫面外時被調用的方法
    void OnBecameInvisible()
    {
        Destroy(this.gameObject);  //刪除遊戲對象
    }

    // Use this for initialization
    void Start () {
        this.GetComponent<Rigidbody>().velocity = new Vector3(-8.0f, 8.0f, 0.0f); //設置向左上方的速度
    }
    
    // Update is called once per frame
    void Update () {
        
    }
}

 

OnBecameInvisible方法是在遊戲對象移動到畫面以外再也不被繪製時被調用的方法。

Destroy(this.gameObject)則是刪除遊戲對象的方法。

注意:若是把參數設置成this的話,刪除的就不是遊戲對象,而是Ball腳本組件。

 

7、防止玩家角色在空中起跳(發生碰撞時的處理)

爲了防止玩家角色在空中再次起跳,咱們來添加下列處理

  • 添加着陸標記
  • 着陸標記值爲false時不容許起跳
  • 將起跳瞬間的着陸標記設爲false
  • 將着陸瞬間的着陸標記設爲true

修改Player腳本,代碼以下:

public class Player : MonoBehaviour {

    protected float jump_speed = 8.0f;  //設置起跳時的速度
    public bool is_landing = false;  //着陸標記

    // Use this for initialization
    void Start () {
        this.is_landing = false;
    }
    
    // Update is called once per frame
    void Update () {
        if(this.is_landing){  //着陸後觸發
            if(Input.GetMouseButtonDown(0)){
                this.is_landing = false;  //將着陸標記設置爲false(未着陸 = 在空中)
                this.GetComponent<Rigidbody>().velocity = Vector3.up * this.jump_speed;
            }
        }
    }

    //添加:和其餘遊戲對象發生碰撞時調用的方法
    void OnCollisionEnter(Collision collision)
    {
        this.is_landing = true;  //將着陸標記設置爲true(着陸 = 在地面上)
    }
}

 

當一個遊戲對象同其餘對象發生碰撞時,OnCollisionEnter方法將被調用。

這是爲了檢查玩家角色是否着陸而添加的。在該方法中把着陸標記的值設爲true。這樣玩家角色就不能在空中再次起跳了。

 

8、禁止玩家角色旋轉(抑制旋轉)

在某種程度上完成了玩家角色和小球的腳本編程後,讓咱們來調整各相關參數,以使角色在起跳後能和小球發生碰撞。

這裏咱們採用下列值:

  • 玩家角色的位置:(-2.0,1.0,0.0)
  • 玩家角色的起跳速度(Player.cs腳本中jump_speed的值):8.0
  • 小球的位置:(5.0,2.0,0.0)
  • 小球的初始速度(Ball.cs腳本中使用Start方法設定的值):(-7.0,6.0,0.0)

1,選擇項目視圖中的Player並打開檢視面板中的Rigidbody標籤下的Constraints項

2,點擊左邊的三角形圖標,下面會進一步顯示Freeze Position和Freeze Rotation

其中Freeze Position對於將遊戲對象的位置座標固定在某些方向上,Freeze Rotation則用於固定其角度。

因爲咱們但願玩家角色只上下跳躍而不作左右和先後的移動,所以:

3,把Freeze Position的「X」「Z」前面的複選框選中。Freeze Rotation方面則把「X」「Y」「Z」所有選中

 

9、讓玩家角色不被彈開(設置重量)

選擇項目視圖中的Ball預設,打開Rigidbody標籤,將Mass項的值由1改成0.01。

 

Mass項用於設定遊戲對象的重量。兩個遊戲對象發生碰撞時,Mass值較大的物體將保持原速度繼續運動,相反Mass值較小的物體則容易因受到衝擊而改變移動的方向。

 

10、讓小球強烈反彈(設置物理材質)

1,建立物理材質

從項目視圖的Create菜單中選擇Physic Material,建立一個新材質並將其名稱改成Ball Physic Material

相對於用來指定顏色等能夠看見的屬性材質,物理材質則是用於設定彈性係數和摩擦係數等與物理運動相關的屬性。

 

2,修改屬性值

在項目視圖中選擇Ball Physic Material後,在檢視面板中選擇Bounciness,將其值由0改成1。這個值越大,遊戲對象越容易被「彈開」。

 

3,將新建立的材質拖拽到Ball預設下的Material

從項目視圖中選擇Ball預設,接着把Ball Physic Material拖拽到檢視面板中Sphere Collider標籤下的Material

 

或者能夠點擊Ball Physic Material右側的圓形圖標。這時Select Physic Material窗口將被打開,在這個「物理材質選擇窗口」中也能夠進行選擇設定

  

 

11、消除「漂浮感」(調整重力大小)

1,在窗口頂部菜單中依次點擊Edit→Project Settings→Physics

檢視面板中將切換顯示PhysicsManager

  

 

2,將Gravity項的「Y」值稍微提升一些,在此設爲-20

 

3,調整參數

經過加強重力能夠減弱物體在運動時的「漂浮感」,不過跳躍的高度和小球的軌道也顯得比原來低了。這種狀況下,咱們能夠考慮調整爲下列數值:

  • 玩家角色的起跳速度(Player.cs腳本中的jump_speed的值):12.0
  • 小球的初始速度(Ball.cs腳本中使用Start方法設定的值):(-10.0,9.0,0.0)

 

12、調整攝像機的位置

1,選擇攝像機後,場景視圖右下角將出現一個小窗口。這是從攝像機看到的畫面。若是沒法看到這個窗口,請在檢視面板中展開Camera標籤

 

2,爲了可以俯視地面,須要使攝像機在往上偏移的同時繞X軸旋轉

調整角度時需把移動工具切換爲旋轉工具。

 用移動工具調整攝像機的位置

  用旋轉工具調整攝像機的角度

 

3,在檢視面板中輸入數值(可根據本身喜愛進行設置)

 

 

4,對比效果

調整攝像機前:

 

調整攝像機後:

 

十3、修復空中起跳的bug(區分碰撞對象)

1,bug的發現

 試玩遊戲後,咱們注意到玩家角色和小球碰撞後還能夠再次起跳。這多是由於防止空中跳躍的代碼存在bug。

2,bug的證實

(1)遊戲啓動後,在層級視圖中選擇Player。能夠在檢視面板中的Player(Script)標籤下看到Is_landing項。這就是在Player腳本中定義過的is_landing變量

 

(2)遊戲剛開始時畫面上尚未小球。隨着玩家角色起跳,能夠看到Is_landing複選框由取消變爲了選中狀態

跳躍過程當中Is_landing爲取消狀態(值爲false)

 

着陸後Is_landing爲選中狀態(值爲true)

 

(3)修改Player.Update方法

void Update () {
        if(this.is_landing){  //着陸後觸發
            if(Input.GetMouseButtonDown(0)){
                this.is_landing = false;  //將着陸標記設置爲false(未着陸 = 在空中)
                this.GetComponent<Rigidbody>().velocity = Vector3.up * this.jump_speed;
                Debug.Break();
            }
        }
    }

 

修改後僅添加了Debug.Break方法的調用。在玩家角色起跳時的瞬間暫停遊戲的運行。

按下播放控制工具條最右邊的按鈕,在逐幀模式下能夠看到玩家角色在一直上升。在玩家角色和小球碰撞的瞬間,Is_landing的值變成了true。(此處沒法截圖,見諒)

搞清楚了bug的緣由,接下來就考慮解決bug的對策。

 

3,bug的解決

(1)首先須要區分開碰撞對象是地面仍是小球

此處咱們能夠利用標籤。須要對遊戲對象的種類進行大體區分時,可使用標籤來分組。

添加標籤到項目中,在項目視圖中選擇Floor預設→點擊Untagged→點擊Add Tag→點擊Tags左側的三角形→點擊「+」→輸入Floor→再次在項目視圖中選擇Floor預設→點擊Untagged→點擊Floor

  

 

 

 

(2),修改腳本

修改Player.OnCollisionEnter方法。在這裏提醒下:記得刪除了以前在Player.Update方法中添加的Debug.Break()。

    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == "Floor")
        {
            this.is_landing = true;  //將着陸標記設置爲true(着陸 = 在地面上)
        }
    }

 

使用了標籤後就能夠區分碰撞對象了。這樣一來就只有在和地面碰撞時,也就是着陸時Is_landing的值纔會變爲true。

 

十4、小結

本次有關Unity入門的學習就暫時先告一段落。經過作一個小遊戲項目的流程,讓我切身體會到使用Unity開發遊戲的大體流程,還有遇到Bug時的分析思路。

固然若是想經過一個小遊戲的製做就學會Unity的所有技能是不可能的,後期在遊戲開發的過程當中,遇到了問題再去查找相應的答案,見招拆招,纔是最有效的。

相關文章
相關標籤/搜索