Unity Dev Memo (2)
October 4, 2020
using UnityEngine;
public class GetMousePos : MonoBehaviour {
Plane plane = new Plane (Vector3.up, 0);
Camera camera;
Vector3 mousePos;
void Start () {
camera = Camera.main;
}
void Update () {
float distance;
Ray ray = camera.ScreenPointToRay(Input.mousePosition);
if(plane.Raycast(ray, out distance)){
mousePos = ray.GetPoint(distance);
}
}
}
Plane plane = new Plane (Vector3.up, 0);
Plane (Vector3 inNormal, float distance)
。inNormal
在距離基準點 distance
的位置創造一個平面。 Vector3.up
就等於 Vector3 (0, 1, 0)
,也就是筆直朝向 Y 軸上方的向量。這個 plane 不會顯示在遊戲中,如果想要用視覺理解 plane 的概念,可以直接在 Editor 中新增一個 rotation 與 position 都為 (0, 0, 0) 的 Plane,這兩個平面基本上相同。 Camera camera;
Vector3 mousePos;
void Start () {
camera = Camera.main;
}
void Update () {
float distance;
Ray ray = camera.ScreenPointToRay(Input.mousePosition);
...
distance
,以及一個射線變數 ray
,起點為攝影機的 near clipping plane,方向為滑鼠位置。Camera.ScreenPointToRay
也就是從 near clipping plane 射向 far clipping plane。 ...
if(plane.Raycast(ray, out distance)){
mousePos = ray.GetPoint(distance);
}
}
plane.Raycast
中的 out
是另一個值得注意的地方。先看 plane.Raycast
函數本身:out
關鍵字一起作為引數輸入。 plane.Raycast
就是有提供 out
回傳值的函數之一,提供的是當相交發生時從 ray 起點至相交點的距離 distance
。因此這一段程式碼的作用是,判斷平面 plane 與 ray 是否有相交發生,如果有的話將距離儲存進 distance。現在射線起點,相交距離都知道了,就能計算出滑鼠位置便是從該射線上從起點開始距離 distance 的地方。ray.GetPoint(0)
),藍色點是與平面相交點( ray.GetPoint(distance)
)。可以看見起點不是攝影機本身,而是在 near clipping plane 上。TerrainCollider
來計算射線與地形 terrain 的相交點。using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GetMousePos : MonoBehaviour {
TerrainCollider terrainCollider;
Camera camera;
Vector3 mousePos;
void Start () {
camera = Camera.main;
terrainCollider = Terrain.activeTerrain.GetComponent<TerrainCollider>();
}
void Update () {
Ray ray = camera.ScreenPointToRay(Input.mousePosition);
RaycastHit hitData;
if(terrainCollider.Raycast(ray, out hitData, 1000)){
mousePos = hitData.point;
}
}
}
terrainCollider
,而這個函數所提供的 out 相交資料也更豐富,不只有距離,而是一整個資料形態 RaycastHit https://docs.unity3d.com/ScriptReference/RaycastHit.html ,包含 point, distance ,collider 等,point 即為射線與 terrainCollider
相交點。terrainCollider.Raycast
追蹤游標位置的展示,可以看見在右側遊戲畫面中游標移至山脈可見的南側時,左側的編輯器畫面也顯示游標位置的藍點直接跳過山脈北側,同時隨著地形一同起伏。Physics.Raycast
。這個函數會抓取引數的射線相交的第一個對象,且同樣提供 out RaycastHit
資料。using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GetMousePos : MonoBehaviour {
Camera camera;
Vector3 mousePos;
void Start () {
camera = Camera.main;
}
void Update () {
Ray ray = camera.ScreenPointToRay(Input.mousePosition);
RaycastHit hitData;
if(Physics.Raycast(ray, out hitData, 1000)){
mousePos = hitData.point;
GameObject hitObj = hitData.collider.transform.gameObject;
}
}
}
Physics.Raycast
的提供距離引數做為判斷相交的最大距離,可以依照自己需求設定。Physics.Raycast
追蹤游標互動物件的展示,使用 RaycastHit.collider.transform.GameObject
判斷射線的碰撞體的原物件之後就可以進行互動。Physics.Raycast
還提供圖層引數過濾判斷射線相交對象。using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HighlightRayOrigin : MonoBehaviour {
Camera camera;
Vector3 mousePos;
LayerMask layerMask = 1 << 8;
void Start () {
camera = Camera.main;
}
void Update () {
Ray ray = camera.ScreenPointToRay (Input.mousePosition);
RaycastHit hitData;
if (Physics.Raycast (ray, out hitData, 1000, layerMask)) {
mousePos = hitData.point;
GameObject hitObj = hitData.collider.transform.gameObject;
}
}
}
Physics.Raycast
的 layerMask
引數就是指定圖層,只有在這個圖層中的物件才會觸發與射線相交的判斷。<<
運算子將指定編號以二進制方式儲存在變數中再傳遞給 Physics.Raycast
函數。