切換
舊版
前往
大廳
主題

【碰撞器應用+UI應用】四、程式說明與應用

澄鷹 | 2018-08-08 00:18:29 | 巴幣 508 | 人氣 3648

  上一節的最後,我們把Healthy與Score物件都掛上了Tag標籤,並且已經用程式將這兩個物件連結起來了。

  這節,我們會去修改掛在Player物件上的「MainCS.cs」腳本,把我們先前說的所有功能都寫進去。說明完程式、確認沒有問題之後,這次的教學就會告一個段落了。

  我們先稍微確定一下我們至今為止做的事情:

  1.在場景中,我們需要新增:
    a.分數
    b.血條
    c.扣血的物件
    d.補血的物件
    e.加分的物件
  2.修改掉多段跳的設定
  3.利用程式使分數、血條增減能正常運作

  我們已經在場景中建立了我們所需要的所有物件,剩下的第二點與第三點,都需要用程式來解決。

  不過,在正式進入程式之前,還有一些之前還沒做完的前置作業必須先做一下。

  那麼,我們開始吧!

========================================================================

  我們之前說,想要讓玩家碰觸到物件時,觸發相關的事件。比如說接觸到加分的物件時,左上角的分數就會增加之類的。

  但是,我們該如何判斷「玩家與物件碰觸」這件事情呢?

  在【新手入門】三、新增物件、場景&元件介紹中,我們有在介紹Box Collider 2D時提到,在這個元件底下有一個「Is Trigger」的選項。觸發器,可以用這個來觸發某一段程式。


  在這次我們所創建的那三個物件中,都會用到這個選項。為此,我們必須在這三個物件底下,都各別新增一個Box Collider 2D元件。但是,個別新增之後又要個別調數值太麻煩了。不知道有沒有人有發現,其實這三個物件的「大小」與「Player」是一樣的?

  那這下就簡單多了,我們直接把Player的Box Collider 2D元件直接複製到那三個物件上就可以了。

  選取Player,按一下在Box Collider 2D元件右上角的選項圖示。


  然後選擇「Copy Component」


  回到Hierarchy中,將「Damage」、「Complement」、「Star」物件選起來。由於都是新增同樣的東西,所以我們打算一起處理。

  ※按住Ctrl可以複選。


  然後點選Transform或Sprite Renderer的選項圖示,選擇「Paste Component As New」


  貼上之後會長這樣:


  這時,我們直接把「Is Trigger」勾選起來。


  如果我們在Inspector中修改時,Hierarchy的選擇狀態是長這樣的話:


  那就表示,被選起來的那三個物件是一起做同樣的修改的。

  現在個別點選「Damage」、「Complement」、「Star」三個物件,應該可以發現他們都被掛上了Box Collider 2D元件,而且「Is Trigger」都已經勾選了。

  這三個物件都已經設定完畢,還有一件事情我們需要調整。

  在前幾節,我們把血條新增出來之後,就這麼放置不管了,但是不曉得有沒有人有發現,我們的血條的數值竟然從一開始就是「0」

  這在遊戲中相當不正常,怎麼有主角剛生出來血條是零的呢?所以,在Hierarchy選擇「Healthy」

  在「Slider」元件下面有一個「Value」的滑條。將他往右滑到最底。


  雖然滑到最底我們的數值也才「1」而已,但這項設定我們先暫時不理他。先這樣就好。

  到目前為止,就是我在一開始說的前置作業。

  前置作業已經完成,可以開始進入程式的部分了。

  選擇「Player」物件之後,將「MainCS.cs」腳本雙擊開啟。

  ※由於程式碼變得越來越長,我不會再加上//a、//b等註解,我會直接用行數來表示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class MainCS : MonoBehaviour {

 public float moveSpeed = 5f;

 Transform trans;
 Rigidbody2D rigid;
 Text score;
 Slider healthy;

 bool isJump = true;
 int scoreCount = 0;

 // Use this for initialization
 void Start () {
  trans = GetComponent<Transform>();
  rigid = GetComponent<Rigidbody2D>();
  score = GameObject.FindGameObjectWithTag
   ("Score").GetComponent<Text> ();
  healthy = GameObject.FindGameObjectWithTag
   ("Healthy").GetComponent<Slider> ();
 }

 // Update is called once per frame
 void Update () {

  if (Input.GetKey(KeyCode.LeftArrow)) {
   trans.Translate(Vector2.left * Time.deltaTime * moveSpeed);
  } else if (Input.GetKey(KeyCode.RightArrow)) {
   trans.Translate(Vector2.right * Time.deltaTime * moveSpeed);
  }

  if (Input.GetKeyDown(KeyCode.UpArrow) && !isJump) {
   rigid.AddForce(Vector2.up * 200);
  }
 }

 void OnTriggerEnter2D(Collider2D other) {
  if (other.gameObject.name == "Damage") {
   healthy.value -= 0.5f;
  } else if (other.gameObject.name == "Complement") {
   healthy.value += 0.3f;
  } else if (other.gameObject.name == "Star") {
   scoreCount += 50;
   score.text = "分數:" + scoreCount.ToString ();
  }
 }

 void OnCollisionEnter2D(Collision2D other) {
  if (other.gameObject.name == "Floor") {
   isJump = false;
  }
 }

 void OnCollisionExit2D(Collision2D other) {
  if (other.gameObject.name == "Floor") {
   isJump = true;
  }
 }
}

  在第三節時我有增加幾行程式,這次我又增加了更多行程式XDD,我們一起來看看:

  8.public float moveSpeed = 5f;
  在原本的設定中,主角移動的速度實在太過緩慢,於是我增加了一個可以在Inspector中隨時變更的公開變數,將這個變數套用在主角移動的公式中,藉此來增減我們的主角移動的速度。
  我直接將主角移動速度的預設值設定為「5」
  在宣告變數時將它宣告成公開變數(public),會讓這個變數在Inspector裡能夠被看見。


  ※這個變數在Inspector裡要顯示甚麼名字,取決於你取的變數名稱。

  ※公開變數這種做法不只可以用在指定物件,只要是任何想要讓他在Inspector中能夠被自由定義的變數,都可以使用這種作法。
  15.bool isJump = true;
  這次我們設定的遊戲架構中的第二點,就是想讓主角不能進行多段跳。於是我宣告了一個布林變數,打算用它來判斷現在主角是不是處於跳躍的狀態,如果是,就禁止再次跳躍。
  由於在原本設計的遊戲場景中,主角最一開始生在半空中,所以在這裡,我設定isJump的預設值為「true」
  16.int scoreCount = 0;
  雖然我們已經新增了一個可以顯示分數的物件,但是那個Text物件的功用是「顯示字串」,字串是無法計算的,所以我們必須在程式中增加一個數值型態的變數,用這個變數來進行計算,計算完之後再轉為字串,最後交由Text物件──也就是我們新增的Score物件來顯示。
  32.trans.Translate(Vector2.left * Time.deltaTime * moveSpeed);
  這一行就是將第八行宣告的公開變數給放進來。因為預設值為「5」,所以直接乘上去之後,會讓主角的移動速度變為原來的五倍。
  第34行也是同樣的概念,只是方向不同而已。
  37.if (Input.GetKeyDown(KeyCode.UpArrow) && !isJump) {
  在向上跳躍的判斷式中,我新增了一小段敘述「&& !isJump」
  「&&」是「And」邏輯閘,表示前後的布林值皆為「true」的時候,才會輸出「true」,除此之外的可能性全部都會輸出「false」
  「isJump」就是我們剛剛在第15行時宣告,用來判斷是否為跳躍狀態的布林變數。
  前面的「!」並不是多打的,「!」為反向邏輯閘,布林值的前面接上這個之後,輸出的布林值就會是相反的。如果「isJump」為「true」,那麼輸出就為「false」,反之,亦然。
  所以這段判斷式的意思就是說:如果玩家按下了向上鍵,「而且」不是處於跳躍狀態」的時候,則執行下面的程式。
  所以,在「!isJump」這一敘述中,要讓他為「true」,必須要「isJump」為「false」才行。也就是說,如果要讓玩家能夠跳躍,必須要是「非跳躍狀態」下才可以。
  42.void OnTriggerEnter2D(Collider2D other) {
  還記得剛剛我們有將Box Collider 2D元件下的「Is Trigger」選項打勾嗎?將這個選項勾選起來之後,這一行程式才有用處。
  這一行程式的意思就是:「當碰到『Is Trigger』選項被勾選的物件的時候,則回傳那個物件的Collider2D資料。」
  「OnTriggerEnter2D」是已經被Unity定義好的方法,就是用來判斷具有「Is Trigger」選項的物件被碰觸的事件。這點在Unity API上能夠查得到。

  根據剛剛我所描述的這個方法的意思來看,如果被碰觸到的那個物件的「Collider2D」系列元件中,「Is Trigger」沒有被勾選起來的話,那麼這個物件即使被碰觸,也無法被這一段程式偵測到。

  另外,OnTriggerEnter2D方法其實還有另外兩個兄弟,分別是「OnTriggerStay2D」、「OnTriggerExit2D」
  他們的差別只是在於「Enter」、「Stay」、「Exit」。這三個方法,分別針對三種不同狀態進行偵測:
    a.Enter:在物件相互碰觸的那一瞬間。
    b.Stay:在物件重疊的那一段時間。
    c.Exit:在物件離開彼此的那一瞬間。
  假設今天有一個A物件穿越了一個B物件。
  其中,Enter與Exit,只會在A物件進入與離開B物件時分別執行一次。
  Stay,則是會在A物件進入B物件之後,每一幀都執行一次。
  這就是這三個方法偵測的事件的差別。

  後面(Collider2D other)的意思則是,被碰觸的那個物件的Collider2D資料,將會被回傳在other這個變數中,所以可以用other這個變數來針對被碰觸的那個物件進行修改。
  43.if (other.gameObject.name == "Damage") {
  剛剛有說,第42行後面括弧內的敘述,是被碰觸的物件回傳的Collider2D資料,被存放在other變數裡。
  這一行判斷式,就是用來確認主角所碰觸的這個物件,究竟是哪一個物件。
  我們可以用主角所碰觸的物件「名稱」,來判斷這個物件究竟是甚麼。
  所以我們會用「name」這個函數來取得物件的名稱。
  不過「name」這個函數取得的名稱,是「物件的名稱」。但是other實際上是一個Collider2D的資料型態,並不是物件,所以無法用「other.name」直接取得物件名稱。
  於是,我們先用「other.gameObject」來取得具有Collider2D的這個物件,然後在後面再加上「.name」來取得這個物件的名稱。
  取得被碰觸的物件的名稱之後,把它拿來做比對,如果它的名稱為「Damage」,則執行接下來的程式。
  44.healthy.value -= 0.5f;
  在第43行,我們已經判斷完了被碰觸的物件了,假設主角被「Damage」物件碰觸的話,那們就會執行這一行程式。
  「healthy」是我們在上一節中就已經宣告過的「血條」的變數。
  「healthy.value」可以用來取得、修改血條的數值。
  由於在當前的設定中,血條最小值為0,最大值為1,增減的數值不可以太大,所以我設定為0.5f
  「-= 0.5f」的意思白話一點就是,把自己減掉0.5。「0.5f」的「f」是資料型態「float」的意思。如果資料型態是「float」的話,請務必在數值後面都加一個「f」。

  這一行程式,就是在碰觸的物件確定為「Damage」之後執行的。
  48.scoreCount += 50;
  剛剛已經有宣告了一個用來記錄分數的數值變數,這一行的意思就是「把自己增加50」
  49.score.text = "分數:" + scoreCount.ToString ();
  「score」是我們在上一節中宣告用來顯示分數的Text型態的變數。
  要讓Text物件能夠顯示出字串,就只要用「Text型態的變數.text」就可以設定要顯示的字串了。

  另外,我們要把我們計算出來的分數代進這個方法之中,讓它顯示在螢幕上。但是根據Unity API所寫的,text方法似乎只能用在「字串」型態的資料上。我們的分數卻是數值型態的資料,無法直接套用。
  這時候只要在數值型態的變數後面加上「ToString()」方法,就可以將這個變數轉換成字串型態的資料了。
  53.void OnCollisionEnter2D(Collision2D other) {
  在第42行的時候有提到,如果碰觸到具有「Is Trigger」的物件,可以用第42行的程式來判斷。但是如果將物件的Is Trigger選項打勾,那麼那個物件就會被穿透過去。
  今天我希望能夠不要穿透過去,但是又能夠偵測到與該物件碰觸的話,那該怎麼辦?
  Unity也有提供這種方法,就是「OnCollisionEnter2D」,他與OnTriggerEnter2D一樣還有另外兩個兄弟,不過意義都是一樣的,我就不再說一次了。
  後面括弧內的意義,也跟第42行的方法一樣,只是回傳的資料型態不同而已。
  之所以會用到這行程式,是因為我想用主角與「地板」的接觸,來判斷主角是不是「跳躍狀態」
  但是地板不可以是可穿透的物體,所以才會用到這個方法。
  這個方法與OnTriggerEnter2D方法的差別,就是OnTriggerEnter2D是偵測「Is Trigger有被勾選」的物件,這個則是偵測「Is Trigger沒有被勾選」的物件,僅此而已。
  55.isJump = false;
  根據第53、54行的敘述,當主角與地板接觸的那一瞬間,就會執行這一行程式
  而這一行就是設定,主角與地板接觸之後,主角就不再是跳躍狀態。
  59.void OnCollisionExit2D(Collision2D other) {
  這一行就是第53行那個方法的兄弟,在「主角離開某個物件的瞬間」就會執行下面的程式。
  61.isJump = true;
  根據59.60行的敘述,主角離開地板後,就會執行這一行程式。
  而這一行就是設定,主角離開地板之後,主角就是跳躍狀態。

  有了53行~63行的相互搭配,「isJump」將會隨著主角離開地面的與否而改變,進而改變主角跳躍的判斷結果。

  今天新增了這幾行的程式,想必我們的遊戲又往前邁進了一步。

  已經將程式碼套用上去的人,不妨可以試玩看看,是不是在碰到左邊那個黃色的物件之後,左上角的分數就會增加了呢?

  碰到綠色的物件血條會上升、紅色的物件血條會下降,主角的移動速度是不是也變得快多了?

  再試試看之前提到的那不合理的現象,狂按上方向鍵看看XDD,是不是已經無法多段跳了?

  如果試著做這些事情,都和我所說的一樣的話,那表示已經沒有問題了。

  ※如果程式套上去之後有錯誤,可能是漏掉了甚麼重要的動作,歡迎在下面留言告訴我和我討論。

  最後,我們再來做最後的確認:

  1.在場景中,我們需要新增:
    a.分數
    b.血條
    c.扣血的物件
    d.補血的物件
    e.加分的物件
  2.修改掉多段跳的設定
  3.利用程式使分數、血條增減能正常運作

  我們之前所想到的新功能、新元素與設定錯誤,全都已經修改完畢。

  這一單元結束,我們了解了該怎麼用Tag的方式與物件做連結,並且也稍微接觸了一點UI介面的設定。也知道了OnCollisionEnter2D、OnTriggerEnter2D等碰撞器相關的應用與程式意義。

  我們的遊戲變得越來越豐富,雖然還是有許多可以更好的地方。這些就等到日後有機會再來加強。

  這一單元的內容開始變得有一點點小複雜,或許不是那麼好理解,也開始有一些繁瑣的設定需要做。如果在製作的途中有遇到甚麼問題的話,歡迎在下方留言告訴我,我們可以一起討論看看XDD。

  那麼,我們【碰撞器應用+UI應用】這個單元的教學也告一段落了。希望至今為止的教學能讓剛接觸Unity的人有些許幫助。

  那就這樣,謝謝大家!

========================================================================

  【碰撞器應用+UI應用】



  四、程式說明與應用

  補、遊戲製作談
送禮物贊助創作者 !
0
留言

創作回應

巴哈姆特活動展覽版主
好猛
2018-10-25 14:14:41
澄鷹
謝謝XDD
2018-10-25 17:12:48

相關創作

更多創作