yafeili 發表於 2015-11-4 16:24:01

感謝你的拋磚引玉~~~

超棒der ~~:kiss:

100735760 發表於 2015-11-3 18:46:24

自動走迷宮

本帖最後由 100735760 於 2015-11-19 14:07 編輯

大家好,我是編號100735760的小嫩嫩,玩Unity也一段時間了,想說丟一點小東西上來拋磚引玉一下。

今天分享的小東西是之前在新莊分校上課時,志鴻大大的課堂作業,下面是迷宮的構造圖很簡單的迷宮,無岔路,
目標就是在不做任何操作下,讓東西從左下跑到右上。
http://d.share.photo.xuite.net/gn00779703/1dbd407/19691745/1104155686_x.jpg
首先根據構造圖建立所需的物件完成後如下圖http://d.share.photo.xuite.net/gn00779703/1dbd44b/19691745/1104159594_l.jpg 基本的物件建立完成後 先別急著寫程式首先我們要先思考 要如何控制我們的主角構想:
[*]一開始就判別障礙物,然後往沒有障礙物的地方前進。
也就是一開始要自動往上走。
[*]每次跟牆壁碰撞時,再次判斷障礙物,然後轉向正確的位置繼續前進。
這邊就要想如何判斷正確的方向

[*]重覆第二步驟,直到終點。
構想完成之後,就可以開始動工啦~首先建立一個C# Script,並掛載到主角cube上。第一步我們要先判斷障礙物的方向,這時候我們可以用Raycast的功能來完成。Raycast 的使用方法有很多種,在這邊我介紹其中一種:  Physics.Raycast (Vector3 origin, Vector3 direction, float distance);翻譯一下就是  Physics.Raycast (起點, 方向, 距離);其結果會回傳一個 bool, 如果從起點開始往方向的距離內有障礙物的話,會回傳 true,反之則回傳 false。所以我們可以先測定一下,主角右方是否有障礙物,在 void Start () 內,寫上:bool hitR = Physics.Raycast (transform.position, Vector3.right, 1.0f);那我們可以用 Debug.DrawRay 來畫線看看是否符合我們的測定範圍。在 void Update () 內Debug.DrawRay (transform.position, Vector3.right, Color.red, 1.0f);完成之後可以先執行看看,結果如下圖:http://d.share.photo.xuite.net/gn00779703/1dbd4b3/19691745/1104166866_l.jpg紅線的長度就是測定範圍,代表一開始就可以測定到障礙物。所以接下來我們就可以把其他的方向補上:http://d.share.photo.xuite.net/gn00779703/1dbd4f2/19691745/1104184849_l.jpg到這邊,第一個階段就算完成一半囉,接下來,要讓主角直接往沒有障礙物的地方前進。根據我們剛剛拿到的資訊,沒有障礙物的方向,就是我們前進的方向:先加上一個全域變數 string GoWhere = "";然後在void Start () 內,加上:http://d.share.photo.xuite.net/gn00779703/1dbd4f3/19691745/1104184850_l.jpg
這樣一來,執行時,就會判斷障礙物,並且依照沒有障礙物的方向給予一個字母。以我們一開始的構造圖來看,一開始會因為 hitU=false,所以 if (!hitU) GoWhere = "U"; 會被執行,所以我們會得到 GoWhere = "U",這也是我們一開始的前進方向。 第二階段,我們要讓主角 cube 碰撞到牆壁時,重新偵測障礙物,並且往新的方向前進。因為我們的主角跟牆壁都是cube內建有Box Collider,只要在void Update () 下方,加上 void OnCollisionEnter(Collision c)。就可以進行碰撞判定。一樣在 void OnCollisionEnter(Collision c),加上偵測障礙物的程式碼:http://d.share.photo.xuite.net/gn00779703/1dbd4f2/19691745/1104184849_o.jpg接下來就是要改變前進的方向,以構造圖第一個轉彎來看,碰撞之後,上方跟右方都是無障礙物的狀況,那我們要如何辨別接下來要往哪走呢?所以我們碰撞之後,除了往哪走之外,還要判斷從哪裡來,所以我們新增一個全域變數 string Comefrom = "";並且在下面新增幾行程式http://d.share.photo.xuite.net/gn00779703/1dbd43d/19691745/1104184156_l.jpg翻譯一下之後就是,如果右邊沒有障礙物,而且不是從右邊來的,那接下來就往右邊走,下面三行以此類推。舉例:第一個轉彎,下方跟右方都是無障礙物,但是我們是從下方來的,所以會符合第一個條件,主角就會往右走。情況相反,主角從右邊來的話,第一個條件會因為 Comefrom = R 而不符,而符合第四個條件,所以會往下跑。完成判斷障礙物跟轉向之後,接下來就是簡單的直線移動了,因為需要持續的前進,所以我們把程式碼寫在 void Update () 中:http://d.share.photo.xuite.net/gn00779703/1dbd47f/19691745/1104181406_l.jpg
這邊也可以使用連續的 if else,那因為排版比較好看的關係,我選擇使用 switch case,這部分很簡單,判斷 GoWhere ,然後給予相對應的移動方向,然後再把 Comefrom 設定成相反的方向即可。 不過執行之後,會發現主角走到底會卡在底部抽搐,我覺得這樣不是很好,所以優化一下,方法也很簡單,我只想讓他走到底之後回頭而已。所以,在 void OnCollisionEnter(Collision c) 原本的判斷式下方再加上幾行,會變成:
http://d.share.photo.xuite.net/gn00779703/1dbd4b3/19691745/1104182994_l.jpg
所以當前面四個判斷式都不符合時,代表正常走法都是死路,就會執行最下面兩行,因為這個迷宮的開頭跟尾巴是上下向,所以我只有寫上下向,如果要增加左右向,可以自行增加。到此,這個簡單的範例就完成了。
最後附上 專案的連結 ,有什麼問題,可以在底下留言,我會盡我所能的解答。
頁: [1]
查看完整版本: 自動走迷宮