Unity - 2D簡易敵人位置指標(使用UGUI)

  簡單製作一個標示敵人位置的功能,同時使用UGUI讓指標顯示在UI面板上,當然還有許多可以增強的功能,不過這邊就單純製作標示位置而已。


  製作的Component裡有使用(Unity - 物件世界座標(World position) <-> UI座標(UGUI position)的互換 )所製作的方法。



  實作測試,箭頭標示敵人方位 (WebGL build) (滑鼠點擊箭頭可讓鏡頭移動到敵人位置)






  首先製作一個箭頭圖片,這邊就用一張三角形來代替,圖片匯入Unity之後打開Sprite Editor視窗,先來編輯Pivot point的位置,把它移動到尖端的地方。


  上圖的Pivot point已經設定到尖端點了,可以看到位置是(0.5, 0.925),數值記下來,之後還會用到。





  接著建立一個UI canvas物件,並且再建立一個Image物件,把剛剛那個箭頭的Sprite圖設定到這Image物件上,調整一個適當的長寬,這邊我Height拉長了一點讓它在畫面中看起來比較像箭頭。


  接著設定這個箭頭的Pivot點,把剛剛Sprite Editor裡面Pivot的數值設定上去,這樣到時候旋轉這個箭頭就會以這個點為中心旋轉。





  接著就來製作一個簡單的Component,來讓這個箭頭動作。
  大致上流程就是:怪物座標- > UI座標 -> 限制UI座標在畫面中 -> 設定箭頭圖片到這個座標 -> 調整箭頭圖片角度。

  參考Class,座標轉換UIPosition.WorldToUI()的方法來自(Unity - 物件世界座標(World position) <-> UI座標(UGUI position)的互換 )。
public class EnemyArrow : MonoBehaviour
{
    public RectTransform uiRect; //UI canvas的RectTransform
    public UnityEngine.UI.Image arrow; //箭頭圖
    
    public MeshRenderer enemy; //我這邊是用顆隨意亂跑的球Mesh,直接抓上來設定

    //這邊就暫時放在Update()裡面讓它每個frame都更新,視自己需求修改
    void Update()
    {
        UpdateArrow(uiRect, enemy.transform.position, arrow);

        //隨意做的一個切換箭頭的顯示,讓敵人在畫面中的時候隱藏箭頭
        arrow.enabled = !enemy.isVisible;
    }

    //更新UI箭頭圖片位置
    private void UpdateArrow(RectTransform r, Vector3 enemyWorldPos, UnityEngine.UI.Image arrow)
    {
        Vector2 enemyUIPos = UIPosition.WorldToUI(r, enemyWorldPos); //怪物世界座標轉換成UI座標

        float width = r.rect.width / 2; //UI一半的寬,因為原點在中心
        float height = r.rect.height / 2; //UI一半的高
        Vector2 uiPos = new Vector2(Mathf.Clamp(enemyUIPos.x, -width, width), Mathf.Clamp(enemyUIPos.y, -height, height)); //限制Image的位置不要超出畫面

        arrow.rectTransform.localPosition = uiPos; //調整箭頭的位置
        float angle = Mathf.Atan2(uiPos.y, uiPos.x) * Mathf.Rad2Deg;
        arrow.rectTransform.localEulerAngles = new Vector3(0, 0, angle - 90); //簡單做個計算角度後調整箭頭讓箭頭朝向敵人,這邊因為箭頭圖片的頂端是在正上方所以angle要減90度
    }
}

  到這邊就完成了,把這個Component掛在物件上,然後把UI canvas的RectTransform跟箭頭的Image抓上去就可以了,敵人我是用個亂跑的球Mesh抓上去,需視情況修改使用。

  這邊要注意一個小問題,就是我這邊用MeshRenderer的isVisible來判斷是否出現在畫面中來隱藏或顯示箭頭,如果編輯Scene的視窗有看到這個物件,也會判斷是在鏡頭前,所以會發生Game視窗沒看到敵人,但箭頭卻隱藏了。

  如果有任何問題或錯誤歡迎提出。



Unity - 物件世界座標(World position) <-> UI座標(UGUI position)的互換

  簡單的來做個座標的轉換,雖然不一定會常常用到,但是某些地方還是有點小用處就是了。


  這次就是把UGUI中的Local物件座標跟世界座標來做個轉換。