iT邦幫忙

2022 iThome 鐵人賽

DAY 10
0
自我挑戰組

老菜雞挑戰30天學爆Unity&C#會成功嗎?...系列 第 10

【Day10】老菜雞學下樓梯遊戲之碰撞方向判斷+法向量簡介(Unity point&normal)

  • 分享至 

  • xImage
  •  

前言

今天仍在探討Player與階梯、Ceiling之間的碰撞關係,由於碰撞判斷還是有所缺失,所以接著要來學習怎麼判斷碰撞的方向,會利用到座標、法向量等概念。


碰撞方向判斷-Unity point

  • 問題:如今的碰撞判斷仍沒有那麼精準,如圖↓

    有沒有發現一開始Player撞到Ceiling時,與Nails階梯又有點卡住的感覺了?原因是由於遊戲一開始執行的currentFloor是紀錄到紅框的這個階梯,
    https://ithelp.ithome.com.tw/upload/images/20220921/20152411F2DZQH6pbm.jpg
    而當我往左走撞到橘框的這個階梯,
    https://ithelp.ithome.com.tw/upload/images/20220921/20152411eMy9wIZS48.jpg
    導致currentFloor改成紀錄橘框階梯,但實際上Player仍是站在紅框階梯上。
  • 解決:故我們需要將碰撞設定為...只有當Player站在階梯上面,也就是碰撞到階梯的上方(紅線所畫之處),才去紀錄currentFloor。
    https://ithelp.ithome.com.tw/upload/images/20220921/20152411am6vJjwoAD.jpg
    由於Player與階梯碰撞的點有兩個↓
    https://ithelp.ithome.com.tw/upload/images/20220921/20152411D8gTYxl72n.jpg
    所以要用point來取得這兩點的座標,
Debug.Log(other.contacts[0].point);
Debug.Log(other.contacts[1].point);

先寫在OnCollisionEnter2D裡,測試看看印出來的座標點長怎樣

void OnCollisionEnter2D(Collision2D other) 
    { 
    if(other.gameObject.tag == "Normal") 
    {
        Debug.Log(other.contacts[0].point);
        Debug.Log(other.contacts[1].point);
        Debug.Log("撞到Normal"); 
        currentFloor = other.gameObject;
    }	 
    else if(other.gameObject.tag == "Nails") 

    { 
        Debug.Log(other.contacts[0].point);
        Debug.Log(other.contacts[1].point);
        Debug.Log("撞到Nails"); 
        currentFloor = other.gameObject;
    } 


從Console欄可以知道這兩點的座標,而當我們知道碰撞到的點在哪之後,就可以得知該點的法向量是多少。

什麼是法向量-Unity normal

  • 所謂的法向量,就是垂直於階梯上這條邊的一個向量,如圖↓
    https://ithelp.ithome.com.tw/upload/images/20220922/20152411HLkS5KJs8V.jpg
    圖中這四個情境的各兩個紅點都位於同一條邊上,故這兩點的法向量都是同一條(紅色箭頭代表法向量)
  • 接著要嘗試把這個法向量輸出出來,可以用到normal ,所以將剛剛程式碼的point改成normal
Debug.Log(other.contacts[0].normal);


可以發現Player如果碰撞到階梯上方,輸出的法向量會是一樣的,如圖都是(0.00,1.00)。

  • 如果往右或往左碰撞到階梯,法向量就會是不同條↓

    往右碰撞到階梯,法向量是(-1.00,0.00)
    https://ithelp.ithome.com.tw/upload/images/20220922/20152411GcoRV2YRBP.jpg
    往左碰撞到階梯,法向量想當然就是(1.00,0.00)
    https://ithelp.ithome.com.tw/upload/images/20220922/20152411Gy4k4S2nWQ.jpg
    所以...我們就可以藉由法向量來判斷Player碰撞到階梯的哪個邊,由於我們只是想讓Player站在階梯上時(碰撞到階梯的上邊)將該階梯記錄到currentFloor,於是判斷式裡要再加上
if(other.contacts[0].normal == new Vector2(0f,1f)) 

因為剛剛發現到Player如果碰撞到階梯上方,輸出的法向量是(0.00,1.00),再修改一下程式碼變成這樣

    if(other.gameObject.tag == "Normal") 
    {
        if(other.contacts[0].normal == new Vector2(0f,1f)) 
        {
             Debug.Log("撞到Normal"); 
            currentFloor = other.gameObject;
        }
       
    }	 
    else if(other.gameObject.tag == "Nails") 

    { 
        if(other.contacts[0].normal == new Vector2(0f,1f)) 
        {
             Debug.Log("撞到Nails"); 
             currentFloor = other.gameObject;
        }
        
    } 

試玩後發現,當Player往左撞到階梯Console欄不會輸出撞到什麼階梯,也不會改變currentFloor,所以碰到天花板尖刺就不會有之前卡住的情況了!


心得

還記得高中數學學到法向量的單元時,都是用來做數學題的計算,今天所學的卻是拿來判斷碰撞方向,果然寫程式與數學觀念還是息息相關的呢!

  • 參考網址:https://www.youtube.com/watch?v=nPW6tKeapsM&ab_channel=GrandmaCan-%E6%88%91%E9%98%BF%E5%AC%A4%E9%83%BD%E6%9C%83
  • 音效、圖片 : 遊戲素材
    (素材由安德斯提供,感謝大大/images/emoticon/emoticon41.gif)

上一篇
【Day9】老菜雞學下樓梯遊戲之Unity GetComponent&Enable Component
下一篇
【Day11】老菜雞學下樓梯遊戲之Unity Component新增血量屬性
系列文
老菜雞挑戰30天學爆Unity&C#會成功嗎?...30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言