iT邦幫忙

2024 iThome 鐵人賽

DAY 25
0
自我挑戰組

Unity入門遊戲開發與實作系列 第 25

【Day 25】經典 Flappy Birds 遊戲實作(三)水管隨機生成和場景移動

  • 分享至 

  • xImage
  •  

昨天我們測試角色飛行的動畫的時候發現一些小問題:每次在動畫切換的時候他都會等一段時間才切換動畫,不會在墜落的時候立即切換墜落的動畫。想要解決這個問題,我們只要點選動畫之間 Transition 的箭頭,把 Has Exit Time 取消打勾,並且設置所有的過度動畫時間為 0 就可以解決這個問題了
https://ithelp.ithome.com.tw/upload/images/20241009/20169301ZTrscZJkFH.png


解決了上次的問題,今天我們要來製作水管和地板的移動!讓角色看起來像是在往前飛一樣。

建造水管

  • 因為水管是一上一下,所以我們先建立一個空物件(Create Empty)取名為 Tube ,再從 Prefab 拉兩根水管到這個空物件中,順便調整一下方向和位置
    https://ithelp.ithome.com.tw/upload/images/20241009/20169301a9epAQyKqw.png
  • 給上下兩個水管都添加 BoxCollider ,這樣小鳥也會與這些水管發生碰撞。需要注意的是,我們還要在包著兩個水管的空物件上也加上 BoxCollider ,同時把 is Trigger 的選項打勾,這個 BoxCollider 就成為了一個觸發器。觸發器不會與物體發生真實的碰撞反應(也就是會直接穿過去),但可以通過函式來偵測碰撞的行為是否發生,這可以用於加分的機制
    https://ithelp.ithome.com.tw/upload/images/20241009/20169301iIiSYdfUaj.png

框框內的長方條就是碰撞器的觸發範圍,上下兩個是水管的 BoxCollider

水管的移動

我們建立一個讓水管移動的腳本,命名為 Tube.cs

// Tube.cs
using UnityEngine;

public class Tube : MonoBehaviour
{
    [SerializeField] private float moveSpeed;
    
    private void Update()
    {
        transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
    }

}

這裡的 transform.Translate() 表示位移的意思,而裡面要填入的是一個三為向量,Vector3.forward 表示向 z 軸( 0, 0, 1)的方向移動。
執行遊戲之後水管就會自己移動了
https://ithelp.ithome.com.tw/upload/images/20241009/20169301Rv1ksLh4VQ.png
https://ithelp.ithome.com.tw/upload/images/20241009/20169301RIHnsRK1Ir.png
但是我們不希望水管無限往後移動,這樣會造成資源的浪費,所以我們要在水管移出範圍之後自動刪除

// Tube.cs
using UnityEngine;

public class Tube : MonoBehaviour
{
    [SerializeField] private float moveSpeed;

    [SerializeField] private float zBound;
    
    private void FixedUpdate()
    {
        transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);  

        if(transform.position.z <= zBound)
        {
            Destroy(gameObject);
        }
    }
}

我們創建了一個 zBound 變數,當水管的 z 座標超過 zBound 時,我們就使用 Destroy(gameObject) 來刪除這個物件。
https://ithelp.ithome.com.tw/upload/images/20241009/20169301Mo0kXOTZqF.png
https://ithelp.ithome.com.tw/upload/images/20241009/20169301xuaAdQybtF.png

當物件超出我們設定的範圍時就會自動被刪除

我們可以把這兩個水管也做成 Prefab ,方便之後的水管生成

隨機生成水管

為了能夠隨機的生成水管,我們需要在場景中有一個物件上面掛著能夠操控這些水管生成,所以我們再創立一個空物件(Create Empty),取名為 TubeSpawner.cs

// TubeSpawner.cs
using UnityEngine;

public class TubeSp : MonoBehaviour
{
    [SerializeField] private Tube tubePrefab;

    [SerializeField] private float spawnMaxY;

    [SerializeField] private float spawnMinY;

    private void SpawnTube()
    {
        Vector3 spawnPos = new Vector3(transform.position.x, Random.Range(spawnMinY, spawnMaxY), transform.position.z);

        Instantiate(tubePrefab, spawnPos, Quaternion.identity);
    }
}

我們宣告了 Tube 的物件,方便之後的生成。接下來在 SpawnTube() 中先宣告一個 Vector3 ,把我們生成的位置填入,例如這邊的 Random.Range(spawnMinY, spawnMaxY) 就表示在 spawnMinYspawnMaxY 之間隨機選一個數。之後就可以套用到 Instantiate() 裡面將水管稱成囉
https://ithelp.ithome.com.tw/upload/images/20241009/201693015xz3qDJiOv.png

TubeSpawner 這個空物件放到水管要生成的地方

但現在執行遊戲不會發生任何事情,因為我們沒有呼叫這個生成水管的方法

每隔一段時間生成水管

為了每隔固定一段時間生成水管,我們需要製作一個計時器

// TubeSpawner.cs
using UnityEngine;

public class TubeSp : MonoBehaviour
{
    [SerializeField] private Tube tubePrefab;

    [SerializeField] private float spawnMaxY;

    [SerializeField] private float spawnMinY;

    [SerializeField] private float spawnTime;

    float timer = 0f;

    private void Update()
    {
        timer += Time.deltaTime;
        if(timer >= spawnTime)
        {
            timer = 0f;
            SpawnTube();
        }
    }
    private void SpawnTube()
    {
        Vector3 spawnPos = new Vector3(transform.position.x, Random.Range(spawnMinY, spawnMaxY), transform.position.z);

        Instantiate(tubePrefab, spawnPos, Quaternion.identity);
    }
}

我們宣告一個 timer 並讓他每次 Update() 的時候都加上 Time.deltaTime ,也就是經過的時間。只要 timer 大於我們的 spawnTime ,我們就呼叫 SpawnTube()!這樣就完成了一個簡單的計時器
執行遊戲後,水管就會每隔一段時間生成囉!
https://ithelp.ithome.com.tw/upload/images/20241009/20169301OG0CZpEs7U.png

會移動的地板

如果單單只有水管在移動,還是少了點鳥在往前飛的感覺,所以我們要來讓地板也會跟著水管向前
https://ithelp.ithome.com.tw/upload/images/20241009/20169301VGC8yooqUG.png
我們複製一塊地板並把他往前拉,我們要創立一個新的腳本,取名為 Floor.cs 來控制這個地板,當地板超過邊界值的時候就把地板的位置設定到最開始,來達成無限地板的效果。
https://ithelp.ithome.com.tw/upload/images/20241009/20169301vtyKRRJQve.png
https://ithelp.ithome.com.tw/upload/images/20241009/20169301w9BPkQeUXe.png
再執行遊戲就能看到地板和水管一起向後移動囉!並且地板會在超出範圍之後自動向後移動。

今天完成了水管移動、水管生成和地板移動的部分,明天我們要來添加計分還有Game Over 的機制!


上一篇
【Day 24】經典 Flappy Birds 遊戲實作(二)建立場景和角色跳躍及動畫
下一篇
【Day 26】經典 Flappy Birds 遊戲實作(四)計分和 GameOver 機制
系列文
Unity入門遊戲開發與實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言