寫在前面

之前開了個坑,現在來填了。操作判斷是個大問題,今天就來總結Unity裡面常用的操作檢測。根據我們開發的應用類型,可分為電腦和手機應用,因此在不同的平臺上操作方式可以分為兩大類:

  1. 電腦端
    1. 鍵盤按鍵控制
    2. 滑鼠點擊控制
  2. 手機端
    1. 觸屏控制
    2. 手勢控制
    3. 重力控制
    4. 陀螺儀控制

本文的限制:1 Unity也支持需要用到手柄或VR頭盔的應用平臺,但在這些平臺上也只不過是對上述操作控制進行變種設計而已,這裡就不展開說了。2 既然涉及到檢測,就一定有對應的移動和轉向等命令,命令的實現有很多種方法。如果講到相關例子,並不代表最佳用法。

正文

絕大多數的輸入判斷,都需要用到Input類,而Keycode類則用來表示鍵盤上的按鍵

Unity - Scripting API: Input?

docs.unity3d.com
圖標
Unity - Scripting API: KeyCode?

docs.unity3d.com
圖標

1 按鍵輸入

與按鍵相關的方法有兩個,一是GetKey(),另一個是GetAxis()

GetKey()例子:

If (Input.GetKey(KeyCode.A))
{
Debug.Log("A pressed");
}

GetKey()方法檢測的是這個按鍵是否被一直按住,GetKeyDown()檢測按鍵被按下,GetKeyU()檢測按鍵抬起。舉個例子,一個推箱子遊戲,每次按下一次按鍵才會向前推進,那麼你就可以使用GetKeyDown。但是像一些即時戰略的遊戲則需要用到GetKey,玩家按住按鍵,自己的角色就會一直往前跑。

GetAxis()例子:

float v = verticalSpeed * Input.GetAxis("Horizontal");
float h = horizontalSpeed * Input.GetAxis("Vertical");
transform.Rotate(v, h, 0);

你可以去Project Settings -> Input中自定義自己的按鍵,比如你可以把空格鍵叫作Fire,使用Input.GetButton("Fire")檢測Space按鍵。

2 滑鼠點擊輸入

檢測哪個滑鼠按鍵被按下,可以使用Input.GetMouseButtonDown()方法,當傳入值為0時,檢測滑鼠左鍵。當傳入值為1時,檢測滑鼠右鍵。當傳入值為2時,檢測滑鼠中鍵。

If (nput.GetMouseButtonDown(0))
{
Debug.Log("Primary Mouse Button Pressed");
}

當然你的手有沒有按下去,這個好說,但是遊戲裡面,遊戲界面上的滑鼠到底有否按到東西呢?或者其他可以用滑鼠實現的想法,例如槍有否打中人呢?這些需要使用到光線投射(Raycast)的物理概念來解釋。在物理層面,如果我們給定一個光源和一個方向,那麼光線就會一直向前跑(假設它在真空中),最後到達一個妨礙它繼續前進的物體表面。

在Unity中,這個物體表面表現為一個帶有碰撞體(Collider)信息的物體。如果發出的射線有穿過任意一個碰撞體,則回傳碰撞體的資訊,其中包括該物件的名稱、世界坐標等。如下圖

Raycast 示意圖

Unity - Scripting API: Physics.Raycast?

docs.unity3d.com圖標

要取得滑鼠點擊的位置,可以用Input.position。我們的Main Camera可以作為起點來創建一條Ray(射線),把攝像機到點擊位置的的向量,當作射線方向。根據這條射線,參考上圖,判斷是否碰到碰撞體。當然,Input類返回的點擊位置不能直接使用,需用Camera.main.ScreenPointToRay()方法將其轉成可用參數

Camera.main其實就等同於GameObject.FindGameObjectWithTag("Main Camera").GetComponent<Camera>(); 這一句。很長對伐!你每次用Camera.main都會調用這麼長一串東西喲!

Camera cam = Camera.main;
Ray ray = cam.ScreenPointToRay(Input.position); // 這是起點產生的Ray
RaycastHit hit; // 這是用來檢測碰撞的Ray,如果有則存入hit內
if (Physics.Raycast(ray, out hit))
{
Debug.Log(hit.transform.name); // 輸出點擊物體名稱
}

Raycast小技巧:

Raycast還可以傳入Layermask來過濾一些你不感興趣的碰撞事件,

Layermask layermask;
if (Physics.Raycast(ray, out hit,layermask))
{
Debug.Log(hit.transform.name); // 輸出點擊物體名稱
}

沒帶有你所設定Layer的物件都會被這條Raycast無視,是不是非常慘。

電腦端完,熱身完了,接下來會繼續填坑的 ...


推薦閱讀:
相關文章