在 Unity入門教程(上) 中咱們建立了一個遊戲項目,而且建立了玩家角色和小球這些遊戲對象,還經過添加遊戲腳本實現了小方塊的彈跳。雖然功能比較簡單,可是完整地表現了使用Unity開發遊戲的大致流程。html
爲了讓這個遊戲變得更加有趣,下面咱們要進一步完善玩家角色和小球的動做。編程
目前小球是靜止在空中的,下面咱們來嘗試讓它朝玩家角色飛去。ide
爲了令小球可以模擬物理運動,須要添加Rigidbody組件。同時還須要建立一個Ball的腳本。此操做在Unity入門教程(上)中的步驟十和步驟十一。工具
添加了Ball腳本之後,咱們要對Start方法做以下修改學習
void Start () { this.GetComponent<Rigidbody>().velocity = new Vector3(-8.0f, 8.0f, 0.0f); //設置向左上方的速度 }
遊戲開始後,小球將向畫面左側飛去this
爲了可以隨時建立出小球對象,首先須要對小球對象進行預設。spa
項目視圖中將出現Ball項。同時,層級視圖中的Ball項文本將會變爲藍色。3d
能夠看到場景中會多出一個小球對象。code
預設了遊戲對象後,咱們就可以很是容易地建立出多個一樣的物體。htm
在項目視圖左上角的菜單中點擊Create→Folder後,項目視圖中將生成一個文件夾,將名字改成Prefabs。
點擊Prefabs文件夾,能夠看到剛纔移動的Ball預設。接着把Player預設和Floor預設也移動到Prefabs文件夾下。
注意在建立前務必先點擊項目視圖左側的Assets圖標以確保當前文件夾回到Assets。
因爲該遊戲對象被用做發射臺,所以命名爲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預設拖拽到這裏(鼠標左鍵按着不要鬆手)。
每次單擊鼠標右鍵時,都會射出一個小球。
這裏,爲了和預設對象分開,咱們把腳本中經過Instantiate方法生成的遊戲對象稱爲實例,把產生實例的過程稱爲實例化。
咱們的遊戲如今出現了一個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腳本組件。
爲了防止玩家角色在空中再次起跳,咱們來添加下列處理
修改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。這樣玩家角色就不能在空中再次起跳了。
在某種程度上完成了玩家角色和小球的腳本編程後,讓咱們來調整各相關參數,以使角色在起跳後能和小球發生碰撞。
這裏咱們採用下列值:
其中Freeze Position對於將遊戲對象的位置座標固定在某些方向上,Freeze Rotation則用於固定其角度。
因爲咱們但願玩家角色只上下跳躍而不作左右和先後的移動,所以:
選擇項目視圖中的Ball預設,打開Rigidbody標籤,將Mass項的值由1改成0.01。
Mass項用於設定遊戲對象的重量。兩個遊戲對象發生碰撞時,Mass值較大的物體將保持原速度繼續運動,相反Mass值較小的物體則容易因受到衝擊而改變移動的方向。
從項目視圖的Create菜單中選擇Physic Material,建立一個新材質並將其名稱改成Ball Physic Material
相對於用來指定顏色等能夠看見的屬性材質,物理材質則是用於設定彈性係數和摩擦係數等與物理運動相關的屬性。
在項目視圖中選擇Ball Physic Material後,在檢視面板中選擇Bounciness,將其值由0改成1。這個值越大,遊戲對象越容易被「彈開」。
從項目視圖中選擇Ball預設,接着把Ball Physic Material拖拽到檢視面板中Sphere Collider標籤下的Material
或者能夠點擊Ball Physic Material右側的圓形圖標。這時Select Physic Material窗口將被打開,在這個「物理材質選擇窗口」中也能夠進行選擇設定
檢視面板中將切換顯示PhysicsManager
經過加強重力能夠減弱物體在運動時的「漂浮感」,不過跳躍的高度和小球的軌道也顯得比原來低了。這種狀況下,咱們能夠考慮調整爲下列數值:
調整角度時需把移動工具切換爲旋轉工具。
用移動工具調整攝像機的位置
用旋轉工具調整攝像機的角度
調整攝像機前:
調整攝像機後:
試玩遊戲後,咱們注意到玩家角色和小球碰撞後還能夠再次起跳。這多是由於防止空中跳躍的代碼存在bug。
跳躍過程當中Is_landing爲取消狀態(值爲false)
着陸後Is_landing爲選中狀態(值爲true)
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的對策。
此處咱們能夠利用標籤。須要對遊戲對象的種類進行大體區分時,可使用標籤來分組。
添加標籤到項目中,在項目視圖中選擇Floor預設→點擊Untagged→點擊Add Tag→點擊Tags左側的三角形→點擊「+」→輸入Floor→再次在項目視圖中選擇Floor預設→點擊Untagged→點擊Floor
修改Player.OnCollisionEnter方法。在這裏提醒下:記得刪除了以前在Player.Update方法中添加的Debug.Break()。
void OnCollisionEnter(Collision collision) { if (collision.gameObject.tag == "Floor") { this.is_landing = true; //將着陸標記設置爲true(着陸 = 在地面上) } }
使用了標籤後就能夠區分碰撞對象了。這樣一來就只有在和地面碰撞時,也就是着陸時Is_landing的值纔會變爲true。
本次有關Unity入門的學習就暫時先告一段落。經過作一個小遊戲項目的流程,讓我切身體會到使用Unity開發遊戲的大體流程,還有遇到Bug時的分析思路。
固然若是想經過一個小遊戲的製做就學會Unity的所有技能是不可能的,後期在遊戲開發的過程當中,遇到了問題再去查找相應的答案,見招拆招,纔是最有效的。