昨天學到如何管理重複性高的物件(Ex.遊戲中的階梯)—用Prefab,而今天就是要寫出如何生成階梯&如何移動階梯的程式碼。
[SerializeField] float moveSpeed = 2f;
Void Update()
{
transform.Translate(0,moveSpeed*Time.deltaTime,0);
//由於現在是要使階梯往上移動,所以就是要設定y軸的移動量
}
→將該檔案掛到物件(Normal&Nails階梯)上→點開Overrides→點Apply All
執行結果
但現在有個問題是...目前建立的階梯往上移動後就沒了,所以接著要來寫出如何不斷生成物件的程式碼~
首先創建一個空物件(命名為FloorManager)來管理、生成這些階梯→把Normal&Nails階梯這些物件都拉進來這個FloorManager裡。
這些物件就是FloorManager物件的子物件,它們之間有父子關係。
接著就可以幫這個FloorManager新增生成階梯的功能...
首先創建一個C#檔案(命名為FloorManager)→而這個檔案不需要用到預設的Start及Update方法故可以將它們刪除→創建生成階梯的方法(因這個方法會在其他地方用到,故要將之設定成public)→創建陣列FloorPrefabs(該陣列是存放我們現在的階梯有哪些)→存檔。
[SerializeField] GameObject[] FloorPrefabs;
public void SpawnFloor()
{
}
→將該檔案掛到物件(FloorManager)上→可以看到右欄顯示出FloorPrefabs→將它點開並新增Normal、Nails的Prefabs(只要將Normal、Nails的Prefabs拉過來)。
之後就可以來寫這個方法的內容了囉!
int r = Random.Range(0,FloorPrefabs.Length);
//隨機從0到這個陣列長度之間挑選一個數字存進r
Instantiate(FloorPrefabs[r],transform);
第一個參數是放想創建的東西(floorPrefabs陣列裡面的第r個值),因為我們希望創建出來的階梯能直接在FloorManager的底下(就是它的子物件),所以可以在後面加上transform這個參數。
何時要讓階梯生成?
由於階梯會一直往上跑,即使跑出我們的遊戲視窗仍不斷往上跑,故我們只要讓階梯跑出遊戲視窗的上方就將之刪掉,同時下面視窗再生成階梯。
如何判斷階梯跑出視窗?
看圖可以發現中心點距離上方視窗有五格的距離,所以就可以設定如果階梯超過y座標為6時就要被刪除,而刪除物件可以用Destroy這個方法。
在Floor.cs這邊要做一個判斷及刪除階梯。
if(transform.position.y > 6f)
{
Destroy(gameObject);
}
transform.parent.GetComponent<FloorManager>().SpawnFloor();
transform.parent代表FloorManager這個物件,因為這些階梯這些階梯,都是 FloorManager的子物件,反之,這些階梯的父物件就是FloorManager。為取得這個物件底下的FloorManager(Script)才能去呼叫它裡面的方法所以要寫.GetComponent().SpawnFloor();代表取得父物件(FloorManager)的Component(名稱為FloorManager)的SpawnFloor方法。
是不是聽起來很饒口呢!
floor.transform.position = new Vector3(Random.Range(-3.8f,3.8f),-6f,0f);
成果~~
附上FloorManager&Floor的程式碼~~
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FloorManager : MonoBehaviour
{
[SerializeField] GameObject[] FloorPrefabs;
public void SpawnFloor()
{
int r = Random.Range(0,FloorPrefabs.Length);
GameObject floor = Instantiate(FloorPrefabs[r],transform);
floor.transform.position = new Vector3(Random.Range(-3.8f,3.8f),-6f,0f);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Floor : MonoBehaviour
{
[SerializeField] float moveSpeed = 2f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.Translate(0,moveSpeed*Time.deltaTime,0);
if(transform.position.y > 6f)
{
Destroy(gameObject);
transform.parent.GetComponent<FloorManager>().SpawnFloor();
}
}
}
今天學到的內容比前幾天稍微複雜,需要用到較多function,但所幸大部分都是Unity內建就有的~