Related Posts Plugin for WordPress, Blogger...

1-4 Using Raycasts To Query Click

本次要使用滑鼠偵測遊戲畫面中點擊到的物件屬於哪個Layer。首先,我們定義兩個Layer:

1. Walkable
2. Enemy

並考慮若滑鼠點擊的物件並未屬於任何我們所定義的Layer,便視為RaycastEndStop。


先隨意點擊場景中任一物件,並從Inspector視窗找到Layer選項。點開後,會看見Add Layer選項。

進入Add Layer畫面後,請在User Layer 8 定義 Walkable,User Layer 9 定義 Enemy。

然後,我將場景中的物件都統一整理到Environment的Empty GameObject中(記得Environment的座標要reset唷)。接著,Environment底下所有物件的Layer都設定為Walkable。
(你可能會發現場景佈置跟上次不太一樣,我只是做了點變化啦,不要太在意哈哈。)

接下來,使用課程提供的CameraRaycaster.cs檔案:


using UnityEngine;

public class CameraRaycaster : MonoBehaviour
{
 //設定偵測Layer的順序,亦即先偵測Enemy,若沒有Enemy才偵測Walkable
    public Layer[] layerPriorities = {
        Layer.Enemy,
        Layer.Walkable
    };

 //使用SerializeField屬性,該變數會出現於Inspector中,且同時為private
 [SerializeField] float distanceToBackground = 100f;
    Camera viewCamera;

    RaycastHit m_hit;
    public RaycastHit hit
    {
        get { return m_hit; }
    }

    Layer m_layerHit;
    public Layer layerHit
    {
        get { return m_layerHit; }
    }

    void Start() // TODO Awake?
    {
        viewCamera = Camera.main;
    }

    void Update()
    {
  // 從layerPriorities中依順序偵測
        foreach (Layer layer in layerPriorities)
        {
            var hit = RaycastForLayer(layer);
            if (hit.HasValue)
            {
                m_hit = hit.Value;
                m_layerHit = layer;
                return;
            }
        }

        // 都沒偵測到,回傳RaycastEndStop
        m_hit.distance = distanceToBackground;
        m_layerHit = Layer.RaycastEndStop;
    }

    RaycastHit? RaycastForLayer(Layer layer)
    {
        int layerMask = 1 << (int)layer; // See Unity docs for mask formation
        Ray ray = viewCamera.ScreenPointToRay(Input.mousePosition);

        RaycastHit hit; // used as an out parameter
        bool hasHit = Physics.Raycast(ray, out hit, distanceToBackground, layerMask);
        if (hasHit)
        {
            return hit;
        }
        return null;
    }
}

你可以複製上面的程式碼,然後再自己新增。新增方式,請從Project中點擊右鍵,選擇Create/C# Script。

然後,我們還需要新增Utility.cs,新增完以後將Unity自動產生的程式碼刪除,並於Utility.cs中定義Layer:
public enum Layer{
 Walkable = 8,
 Enemy = 9,
 RaycastEndStop = -1
}


接著就可以將CameraRaycaster.cs檔案拖曳到Camera Arm中了。

再從Camera Arm新增Cursor.cs,撰寫程式碼,從Camera Raycaster取得目前滑鼠點擊到的物件Layer。


using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Cursor : MonoBehaviour {

 CameraRaycaster cameraRaycaster;

 void Start () {
  //取得Camera Arm中的Camera Raycaster,因為Cursor.cs也是放在Camera Arm之下,故可以直接用GetComponent取得。
  cameraRaycaster = GetComponent ();
 }
 
 void Update () {
  //於Console中顯示滑鼠點擊到的Layer
  print (cameraRaycaster.layerHit);
 }
}

最後執行結果,會看見Console出現Walkable,這是因為目前介面上只有Walkable物件,後面再來新增Enemy。

留言