2024 虛擬實境 x 人因設計 13Unity 保齡球遊戲拆解&製作

更新於 發佈於 閱讀時間約 11 分鐘

我們完成了保齡球發射,再來來處理球瓶囉!!

在這之前,我們在學一個程式語言中也算蠻重要的語法....,然後看看怎麼運用到遊戲裡面 :)

For迴圈(loop)

(好像會很麻煩,但我們還是痛苦一下才會進化><)


這看的出來是操場嘛,迴圈的概念就是重複執行,像是繞著操場跑步一直做一樣的事情,通常用於對集合(例如清單、字串、元組等)中的每個元素進行迭代操作。

raw-image

蛤~迭代?

#迭代(iteration)是重複回饋過程的活動,其目的通常是為了接近並且到達所需的目標或結果。每一次對過程的重複被稱為一次「迭代」,而每一次迭代得到的結果會被用來作為下一次迭代的初始值。


常常看到的迴圈有兩種 While & For,這兩個差在哪邊?

觀察兩種迴圈的結構如下:

While迴圈:

while (執行條件) {
重複執行的程式們}

For迴圈:

for (宣告索引變數; 執行條件; 每次迭代索引變數的變化) {
重複執行的程式們}

可以發現最大的差異就在於有沒有宣告索引變數,而for loop因為宣告了索引變數,所以可以記錄目前跑了幾次迴圈,迴圈次數到了就可以跳出迴圈了。相對的While不須宣告索引變數,只要執行條件仍然滿足,就可以一直迴圈下去。因此,當迭代次數已知,也就是當你知道要跑幾次迴圈時,可使用for迴圈;而當只知道迴圈執行條件,而不清楚總共需跑幾次迴圈時,就只能使用While迴圈

就好像狗狗繞圈圈 :

如果要讓小狗繞10圈,可用for迴圈;如果要讓小狗一直跑到主人回到家,但不知道會跑幾圈時,就只能用while迴圈。

程式碼示意如下(在這裡暫且以文字代替真正的程式碼,以著重在兩種迴圈的比較):

  • 跑十圈:
for (let i = 1; i <= 10; i++) 
{
小狗繞一圈
}
  • 一直跑到主人回到家:
while (主人還沒到家)
{
小狗繞一圈
}


While迴圈也可完成for迴圈的任務

但其實while迴圈也可達成for迴圈的任務,只要自行在「迴圈外」宣告索引變數」,並在「迴圈內」寫入每次迭代時索引變數的變化,就可達到同樣的效果,如下:

let i = 1
while ( i <= 10)
{
小狗繞一圈
i++
}

兩種寫法主要的差異在於:

  1. 索引變數的有效範圍: for迴圈的索引變數只在迴圈內有效,而while的則在圈外也有效。
  2. 索引變數變化的位置: for迴圈一律在進入迴圈前;而while則可任意選擇其在迴圈內的位置。

在舉個例:

for 迴圈適合以下情境:

    • 當你知道需要迭代的確切次數時,for 迴圈是最適合的選擇。
    • 例如:瀏覽列表、字典、元組或範圍內的數值。
fruits = ['apple', 'banana', 'cherry']
for fruit in fruits:
print(fruit)


while 迴圈適合以下情境:

迭代次數未知但需要根據條件迭代的情況

  • 當迭代次數不確定,並且需要根據某個條件來決定迭代是否繼續時,while 迴圈是最佳選擇。
  • 例如:等待用戶輸入正確的數據或處理數據直到特定條件滿足。
user_input = ''
while user_input.lower() != 'exit':
user_input = input('Enter something (type "exit" to quit): ')
print('You entered:', user_input)


這樣看來,while迴圈好像有更多的彈性,但相對的也可考量: 索引變數在迴圈外還會需要使用嗎? 若在迴圈外不再需要使用,但在迴圈外仍有效的話,是否只是佔用了多餘的儲存空間,並讓變數的管理更為複雜呢 ?



來練習一下

for (初始變數; 判斷式; 遞增式)

for (i = 0; i<j; i++)

新增一個程式碼,可命名ForLoopMath ,先把他賦予在某物件上,這樣按Play鍵他才會執行。

宣告兩個變數-開始整數 & 結束整數

public int StartNumber = 0;

public int EndNumber = 0;

我們只執行一次,先把它寫在Void Start 裡面

for (StartNumber = 0; StartNumber < EndNumber; StartNumber++)

{

print(StartNumber);

}

raw-image

這是數列的練習,再試個字串(String)的試試~~

宣告一個字串變數

public string[] fruits = { "apple", "orange", "banana" };

一樣只須執行一次所以寫在Start

void Start()

{

// 使用 for 迴圈輸出字串列表的每個元素

for (int i = 0; i < fruits.Length; i++)

{

print(fruits[i]);

}

}

raw-image

好,準備一個GameObject(保齡球球瓶),一個空物件(定位用),還有一個新腳本BowlingPinCreate

打開新腳本後

宣告三個公開變數:

一個是球瓶數量 , 一個是創建球瓶的, 另一個是創建球瓶的起始位置

public int totalBowlingBalls = 5;

public GameObject bowlingBall;

public Transform initialBallPosition;

raw-image


再來試著用for迴圈創建N個球瓶
for (int i = 0; i < totalBowlingBalls; i++)

{

Vector3 ballPosition = Vector3.zero;

// 如果有設置初始位置,則使用初始位置,否則使用計算的位置

if (initialBallPosition != null)

{

ballPosition = initialBallPosition.position + new Vector3(i * 6, 0.5f, 0);

}

else

{

ballPosition = new Vector3(i * 6, 0.5f, 0);

}

Instantiate(bowlingBall, ballPosition, Quaternion.identity);

}

}

raw-image

之後這個腳本附加在地板或其他GameObject上,就是不要附在創建球瓶的上面

(不然會很恐怖,Unity 會直接當掉)

生完球瓶,那就來遊戲的重點啦,讓球瓶倒掉~~

那我希望全部的球瓶倒掉我就贏了,那換句話說就是

「我擊倒的球瓶數達到原本數量就贏了!」

來囉~


先為每個保齡球物件添加了一個名為 PinCollider 的腳本,用於追蹤保齡球的狀態。

GameObject ball = Instantiate(bowlingBall, ballPosition, Quaternion.identity);

// 添加 PinCollider 腳本以追蹤保齡球狀態

ball.AddComponent<PinCollider>();

raw-image

不對阿,我們沒有PinCollider的腳本,所以要再建立一個,這個的內容是我們要看球瓶有沒有碰到地板。

PinCollider腳本這樣寫

private void OnCollisionEnter(Collision collision)
{
// 碰撞到地板時通知 Finish類別已擊倒了
if (collision.gameObject.CompareTag("Finish"))
{
BowlingPinCreate game = FindObjectOfType<BowlingPinCreate>();
if (game != null)
{
game.UpdateKnockedDownBalls();
}
}
}
raw-image

找場景中的第一個 BowlingPinCreate 類別實例


之後回去BowlingPinCreate腳本 新建 ​UpdateKnockedDownBalls()的方法

新增一個私有變數 private int knockedDownBalls = 0; // 已擊倒的保齡球數量

raw-image
 public void UpdateKnockedDownBalls()
{
knockedDownBalls++;

// 檢查是否達到贏得遊戲的條件
if (knockedDownBalls >= totalBowlingBalls)
{
Debug.Log("Congratulations! You win the game!");
}
else
{
Debug.Log("Knocked down balls: " + knockedDownBalls);
}
}

就可以試著射球瓶看看~~


ㄟ等等,他A球瓶如果碰地板兩次,會+2,這不是我們要的結果吧!正常是一球瓶倒只會+1,所以要回去改球瓶碰撞器的腳本PinCollider,讓他碰到地板一次後就不會再偵測了


private bool hasCollided = false; // 標記是否已經計算過碰撞

public class PinCollider : MonoBehaviour
{
private bool hasCollided = false; // 標記是否已經計算過碰撞

private void OnCollisionEnter(Collision collision)
{
if (!hasCollided && collision.gameObject.CompareTag("Finish"))
{
BowlingPinCreate game = FindObjectOfType<BowlingPinCreate>();
if (game != null)
{
game.UpdateKnockedDownBalls();
}
hasCollided = true; // 設置已經計算過碰撞
}
}
}
留言
avatar-img
留言分享你的想法!
avatar-img
Gavin Hsieh ㄉ基地
4會員
20內容數
Gavin Hsieh ㄉ基地
Gavin Hsieh ㄉ基地的其他內容
2024/05/29
上週的作業保齡球規則 Student A 角色:玩家1、玩具球、娃娃A、娃娃B、娃娃C 規則:打擊娃娃,要贏得遊戲需要使用玩具球打擊到娃娃,共有三次機會可以打擊,全部娃娃都有被打擊到就能贏得勝利,如三次機會中只打擊到其中一隻/兩隻娃娃,另外沒被打擊到的娃娃會消失,遊戲立即結束! Studen
2024/05/29
上週的作業保齡球規則 Student A 角色:玩家1、玩具球、娃娃A、娃娃B、娃娃C 規則:打擊娃娃,要贏得遊戲需要使用玩具球打擊到娃娃,共有三次機會可以打擊,全部娃娃都有被打擊到就能贏得勝利,如三次機會中只打擊到其中一隻/兩隻娃娃,另外沒被打擊到的娃娃會消失,遊戲立即結束! Studen
2024/05/29
剩下兩週上課囉,大家加油!! 在一開始我們在課程完成了椅子(角色的移動嘛),但遠遠的看著他移動好像缺少了一些遊戲體驗 嗎?>< 這週我們就來改變遊戲的視角吧~~ 來看一下兩個版本的比較~~ 原本WASD AD控制Y軸旋轉(轉頭),後來改成WASD控制平移座標,把旋轉特別移出來到滑鼠上,
Thumbnail
2024/05/29
剩下兩週上課囉,大家加油!! 在一開始我們在課程完成了椅子(角色的移動嘛),但遠遠的看著他移動好像缺少了一些遊戲體驗 嗎?>< 這週我們就來改變遊戲的視角吧~~ 來看一下兩個版本的比較~~ 原本WASD AD控制Y軸旋轉(轉頭),後來改成WASD控制平移座標,把旋轉特別移出來到滑鼠上,
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
這篇內容,將透過實戰教學,介紹GameMaker中的Event。包括Event的簡介、Create的講解、Step的講解、Events的基本操作。
Thumbnail
這篇內容,將透過實戰教學,介紹GameMaker中的Event。包括Event的簡介、Create的講解、Step的講解、Events的基本操作。
Thumbnail
這篇內容,將透過實戰教學,介紹GameMaker中的Sprite。包括建立新的Sprite、重新命名及刪除、建議的命名方式、編輯圖像、調整圖像大小、動畫的概述、原點設置、碰撞遮罩的概述。
Thumbnail
這篇內容,將透過實戰教學,介紹GameMaker中的Sprite。包括建立新的Sprite、重新命名及刪除、建議的命名方式、編輯圖像、調整圖像大小、動畫的概述、原點設置、碰撞遮罩的概述。
Thumbnail
令人著迷的扭蛋~~
Thumbnail
令人著迷的扭蛋~~
Thumbnail
這篇文章介紹瞭如何使用Raspberry Pi PICO等材料製作自己的GAME&WATCH大金剛掌機,以及接線圖、程式碼下載和安裝遊戲的教學,並且分享了製作過程中的一些心得和回憶。如果您對童年的遊戲回憶感興趣,這篇文章值得一讀。
Thumbnail
這篇文章介紹瞭如何使用Raspberry Pi PICO等材料製作自己的GAME&WATCH大金剛掌機,以及接線圖、程式碼下載和安裝遊戲的教學,並且分享了製作過程中的一些心得和回憶。如果您對童年的遊戲回憶感興趣,這篇文章值得一讀。
Thumbnail
這篇文章是CONTORL直播的第三部分,介紹了遊戲的內容和心得。作者表示遊戲中的戰鬥逐漸熟練,敵人種類增加,場景也更加精彩。他使用了變聲器增加了娛樂效果,並提到遊戲的難度設計很平衡,場景設計獨特,劇情引人入勝。心得部分,作者表示遊戲很好玩,戰鬥有挑戰性但不過分,劇情和配音也很出色。
Thumbnail
這篇文章是CONTORL直播的第三部分,介紹了遊戲的內容和心得。作者表示遊戲中的戰鬥逐漸熟練,敵人種類增加,場景也更加精彩。他使用了變聲器增加了娛樂效果,並提到遊戲的難度設計很平衡,場景設計獨特,劇情引人入勝。心得部分,作者表示遊戲很好玩,戰鬥有挑戰性但不過分,劇情和配音也很出色。
Thumbnail
童一心得 @ 2023 10/21 〔蕃薯 北極熊班〕
Thumbnail
童一心得 @ 2023 10/21 〔蕃薯 北極熊班〕
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News