簡單的推幣機範例 Part1


















本篇承接 簡單的 Logo 場景(淡入淡出效果) , 首先來完成上篇最後提到的如何串接場景,我們先在 Project 視窗中新增 1 個場景,名稱自訂 (MainGameScene), 開啟 Logo 場景腳本在最後 1 段加入串接場景的方法,如下

   1:      else if(gameFlow==2)    
   2:      {
   3:          logoGUI.guiTexture.color.a-=0.2*Time.deltaTime;
   4:          if(logoGUI.guiTexture.color.a<=0)
   5:          {
   6:              Application.LoadLevel("MainGameScene");
   7:          }
   8:      }

第 6 行 Application.LoadLevel("MainGameScene"); 就是串接下 1 個場景的方法,注意使用這個方法之前必須在 Unity 中先設定場景的名稱和順序,步驟如下

File -> Build Settings -> 在 Scenes In Build 視窗就是所有場景的順序(預設是空白的),接著按下 Add Current,目前的場景就會出現在 Scenes In Build 視窗

在每個場景名稱後面都會有個數字,你也可以使用數字來代替場景名稱輸入到串接的方法中,執行看看吧, Logo 場景結束後就會接到 MainGameScene 場景!!!

完成串接場景的功能後,我們開始來實作簡單的推幣機範例,首先新增 2 個方塊物件,其中 1 個置放在另 1 個的上方,上方的方塊改名為 upFloor,下方為 downFloor,我們準備讓上方的方塊 (upFloor),沿著 X 軸不斷前後移動以推動金幣落下, upFloor 可以說是恆動體,必須對 upFloor 物件作一些設定

1.加入 Rigidbody 元件 (為了和金幣物件有真實碰撞物理效果)
2.把 Rigidbody 的 Use Gravity 取消 (避免摩擦力的產生)
3.把 Constraints 的 Freeze Rotation Y,Z 勾選 (避免方向旋轉)
4.把 Mass (質量) 增加 (以推動金幣)

完成機台物件之後,來製作金幣吧,我們使用 Unity 內建的 Cylinder (圓柱)物件來製作,新增 Cylinder 並調整尺寸,改名為 coin , 調整完尺寸之後會發現它的碰撞區域大於整個體積,由於預設的碰撞器 (collider)為 Capsule collider (膠囊型碰撞器),很難調整成合適的大小,所以我們移除它並新增 Mesh collider (網格碰撞器),調整完碰撞器,我們把金幣物件做成 Prefab (預製物),方便我們在遊戲中隨時新增金幣, Prefab 的詳細使用可參考此篇,接下來也會簡單示範 Prefab 的製作方法,步驟為

Project 視窗點選右鍵 -> Create -> Prefab

你會看到 1 個白色的物件 (Prefab) 出現在 Project 視窗中,接著把剛剛建立的 coin 物件直接拖曳到白色的物件上,此時會變成藍色物件 Prefab 建立完成,金幣和機台建立完成後,接下來我們就能開始寫腳本了,新增腳本並附屬給 Camera ,腳本內容如下

   1:  #pragma strict
   2:   
   3:  var upfloor : GameObject ;
   4:   
   5:  var upfloorActDir : int;
   6:   
   7:  var coinNum : int ;
   8:   
   9:  var coinNumGUI : GameObject;
  10:   
  11:  var coinOrigin : GameObject;
  12:   
  13:  function Start () 
  14:  {
  15:      upfloor = GameObject.Find("upFloor");
  16:      upfloorActDir = 0;
  17:      
  18:      coinNum = 100;
  19:      
  20:      coinNumGUI = GameObject.Find("CoinNumGUI");
  21:  }
  22:   
  23:  function Update () 
  24:  {
  25:      detectTouch();
  26:      
  27:      showCoinNum();
  28:  }
  29:   
  30:  function FixedUpdate()
  31:  {
  32:      upfloorAct();
  33:  }
  34:   
  35:  function detectTouch()
  36:  {
  37:      if(Input.touchCount>0)
  38:      {
  39:          var touch1 = Input.GetTouch(0);
  40:          
  41:          if(touch1.phase==TouchPhase.Began)
  42:          {
  43:             
  44:              
  45:              makeCoin(touch1.position.x);
  46:          }
  47:          
  48:      }
  49:  }
  50:   
  51:  function upfloorAct()
  52:  {
  53:      if(upfloorActDir==0)
  54:      {
  55:          upfloor.transform.Translate(0.5*Time.deltaTime,0,0);
  56:          
  57:          if(upfloor.transform.position.x>=0.8)
  58:          {
  59:              upfloorActDir =1;
  60:          }
  61:      }
  62:      else if(upfloorActDir==1)
  63:      {
  64:          upfloor.transform.Translate(-0.5*Time.deltaTime,0,0);
  65:          if(upfloor.transform.position.x<=-0.8)
  66:          {
  67:              upfloorActDir =0;
  68:          }
  69:      }
  70:  }
  71:   
  72:  function makeCoin(screenX:float)
  73:  {
  74:      if(coinNum>0)
  75:      {
  76:          coinNum-=1;
  77:          
  78:          var tempz = -13 + ((screenX / 8) * 0.1);
  79:          
  80:          Instantiate(coinOrigin,Vector3(0.8,1.8,tempz),transform.rotation);
  81:          
  82:          
  83:      }
  84:  }
  85:   
  86:  function showCoinNum()
  87:  {
  88:      coinNumGUI.guiText.text = coinNum.ToString();
  89:  }

第 1 行為效能有關,簡單的說 Unity 為了效能考量建議腳本語言使用靜態型別(static typing)取代動態型別(dynamic typing), 如果在該腳本第 1 行使用 #pragma strict 
 那麼在後面的程式碼都禁止使用動態型別,一但使用動態型別, Unity 就會報錯
第 3 行 upfloor 為上層方塊物件,我們會讓它不斷移動以推動金幣
第 5 行 upfloorActDir 為上層方塊物件的動作索引,數值為 0, X 軸會增加,數值為 1, X 軸會減少
第 7 行 coinNum 為目前的金幣數,數值為 0 就無法再投擲金幣
第 9 行 coinNumGUI 用來顯示金幣數量, GUI 的詳細用法請參考此篇
第 11 行 coinOrigin 是金幣的預製物,我們使用它來產生金幣
第 13 ~ 21 行為 Start 方法,我們把數值的初始化都放在這
第 15 行使用 GameObject.Find("upFloor"); 尋找上層方塊物件
第 16 行設定動作索引為 0
第 18 行設定一開始的金幣數量為 100
第 20 行設定顯示金幣的 GUI
第 23 ~ 28 行為 Update 迴圈,第 25 行為偵測觸碰的方法,第 27 行為顯示金幣數量 GUI 的方法
第 30 ~ 33 行為FixedUpdate 方法,裡面放置上層方塊的動作方法
第 35 ~ 49 行為偵測觸碰的方法,原理和此篇相同,其中第 45 行的 makeCoin(touch1.position.x); 為產生金幣方法
第 51 ~ 70 行為上層方塊移動方法,第 53 行當方塊動作索引為 0 時,第 55 行會不斷增加 X 軸的數值,以螢幕畫面來看的話就是往前移動,第 57 行當 X 軸數值增加到 0.8 時,改變方塊的動作索引為 1 ,不斷減少方塊的 X 軸數值,看起來就像往後移動,這裡的 0.8 要看自己的方塊物件移動情況而定,接下來的 62 ~ 69 行類似上述情況
第 72 ~ 84 行為產生金幣的方法,首先第 74 行限制只有金幣數量大於 0 才能產生金幣,第 76 行金幣數量減少,第 78 行為觸碰螢幕座標和世界座標的轉換,這裡說明一下轉換座標的方式,觸碰螢幕的座標只有 X 座標和 Y 座標, 2維向量,如下圖

















只要計算 X 座標再依比例轉換到世界座標中,就完成了
第 80 行 Instantiate(coinOrigin,Vector3(0.8,1.8,tempz),transform.rotation); 為產生金幣的方法,第 1 個物件為想要複製的物件, coinOrigin 必須在腳本的屬性欄位設定,至於設定的值就是我們剛剛提到的 Prefab 容器,第 2 個參數為物件的座標,其中的 0.8 , 1.8 為固定值,依照遊戲而定, tempz 就是我們轉換完成的世界座標 Z 值,,第 3 個參數為物件的旋轉方向 transform.rotation 為 Prefab 物件的原值
第 86 ~ 89 行為顯示金幣 GUI 的方法

主要遊戲流程腳本到這裡已經完成,而在 Prefab 容器我們還必須加上刪除自己的腳本,當金幣本身被推落時,除了增加金幣數量以外,就沒有其他作用了,所以掉落之後我們就能把它刪除掉,刪除腳本內容如下

   1:  #pragma strict
   2:   
   3:  var deletePlane : GameObject ;
   4:   
   5:  var coinAddNum : int ;
   6:   
   7:  function Start () 
   8:  {
   9:      deletePlane = GameObject.Find("downFloor");
  10:      
  11:      if(gameObject.name.Equals("SmallCoin1(Clone)") || gameObject.name.Equals("SmallCoin1"))
  12:      {
  13:          coinAddNum = 1;
  14:      }
  19:  }
  20:   
  21:  function Update () 
  22:  {
  23:      destroySelf();
  24:  }
  25:   
  26:  function destroySelf()
  27:  {
  28:      if(transform.position.y < deletePlane.transform.position.y-10)
  29:      {
  30:          GameObject.Find("MainGameFlow").GetComponent(MainGameScript).coinNum+=coinAddNum;
  31:          Destroy(gameObject);
  32:          
  33:          
  34:      }
  35:  }

第 1 行如前面所述為了效能考量而用
第 3 行 var deletePlane 當金幣掉落到某個程度(Y 軸)時,我們就能把它刪除,所以我們在下層方塊底部新增 1 個 Plane 平面,來偵測是否刪除
第 5 行 var coinAddNum 當金幣刪除前,還必須加入增加目前的金幣數量
第 7 ~ 19 行也是初始化的設定,第 9 行尋找刪除平面,第 11 行為判斷目前物件名稱來決定增加金幣的數值,如果有大小金幣或是其他寶物掉落,增加的金幣數值就能調整,第 21 ~ 24 行為 Update 迴圈,裡面只有 1 個方法,偵測是否刪除自己
第 26 ~ 35 行就是偵測是否刪除自己的方法,第 28 行判斷物件本身的 Y 座標是否超過刪除平面物件,第 30 行比較特殊,首先尋找 MainGameFlow物件(控制主要遊戲流程的物件),再尋找附屬在該物件上的腳本 MainGameScript ,最後再取得該腳本中的數值 coinNum ,並增加它
第 31 行刪除自己本身
最後記得把這個腳本附屬在 Prefab 物件上

執行看看吧~ 你會有 1 個非常 "基本" 的推幣機遊戲

接下來的幾篇會針對推幣機範例加入許多功能喔~~~



標籤: