Unity中的輸入

任何遊戲都應該提供給用戶交互的方式,能夠想象一個沒有任何交互的遊戲是什麼樣的。若是沒有輸入系統帶來的,用戶與遊戲的交互那麼遊戲將再也不是遊戲,由於玩家將不能進行任何操做,那還怎麼玩呢?Unity做爲一個號稱跨平臺性能最好的遊戲引擎,那麼它給咱們提供了哪些輸入呢?爲了可以更好的整理Unity的輸入系統,暫時將其分爲移動平臺的輸入和傳統的輸入。ide

移動平臺的輸入

在手機和pad上主要的輸入方式就是:觸摸,重力加速器,虛擬鍵盤等。Unity將這些操做都封裝到了UnityEngine.Input和UnityEngine.TouchScreenKeyboard這兩個類裏。函數

觸摸

觸摸相關的函數

在UnityEngine.Input類中爲咱們提供了觸摸相關的函數,以及在UnityEngine命名空間中涉及到的類,相關函數和類以下表:性能

函數表:
|函數名 |做用
----|-----
multiTouchEnabled| 是否啓用多點觸摸
simulateMouseWithTouches| 啓用/禁用使用觸碰仿真鼠標的操做
touchCount| 在此幀中的觸摸數量
touches|在上一幀中的觸摸點(Touch)信息
touchSupported| 標示當前運行此程序的設備是否支持觸摸
GetTouch|根據觸摸點的索引獲取觸摸點的信息
類表:
類名 |做用
---|--
Touch| 觸摸點信息
TouchPhase| 觸摸點的狀態信息測試

觸摸的一個示例

此示例主要實現以下三個功能:this

  1. 顯示觸摸點的屬性信息
  2. 顯示點擊到的物體
  3. 測試仿真鼠標

示例代碼,以下:3d

public class TouchInputTest : MonoBehaviour {

    public Camera m_mainCamera = null;    
    private bool m_isRatating = false;
    private GameObject m_objRatation = null;
    private float m_nSpeedRatation = 30.0f;
    private float m_nTotalAngle = 0;
    private const int nMaxSelectedSize = 5;
    private string[] m_strSelectedGameObject = new string [nMaxSelectedSize]{"", "", "", "", ""};
    // Use this for initialization
    void Start () 
    {

    }

    // Update is called once per frame
    void Update () 
    {
        //將是否支持觸碰
        if (Input.touchSupported)
        {        
            print("Number of touches:" + Input.touchCount);
            print("Length of touches:" + Input.touches.Length);
            print("---------------------------------------------");
            for (int i = 0; i < Input.touches.Length; ++i )
            {
                Touch tch = Input.touches[i];
                //打印觸摸點的信息
                print("Index:" + tch.fingerId);
                print("State:" + tch.phase.ToString());
                print("Positon:" + tch.position);
                print("TapCount:" + tch.tapCount);
                print("deltaPosition:" + tch.deltaPosition);
                print("deltaTime:" + tch.deltaTime);

                //經過射線拾取物體
                if (m_mainCamera != null)
                {
                    Ray ray = m_mainCamera.ScreenPointToRay(tch.position);
                    RaycastHit rayHitInfo;
                    Physics.Raycast(ray, out rayHitInfo);
                    if (rayHitInfo.transform)
                    {
                        if (0 == i)
                            m_objRatation = rayHitInfo.transform.gameObject;
                        m_strSelectedGameObject[i] = rayHitInfo.transform.name;
                    }
                    else
                    {
                        m_strSelectedGameObject[i] = "";
                    }
                }
                else
                {
                    print("Main camera is null.");
                }
            }

            for (int i = Input.touches.Length; i < nMaxSelectedSize; ++i)
            {
                m_strSelectedGameObject[i] = "";
            }


            //檢測是否支持使用觸摸仿真鼠標操做。1個手指操做爲左鍵,2個手指操做表明右鍵,3:個手指表明中鍵
            //這你經過兩個手指單機,來模仿鼠標右鍵單擊,單兩個手指單擊時,選中的物體沿Y軸旋轉360度。
            if (Input.simulateMouseWithTouches)
            {               
                if (Input.GetMouseButton(1) && !m_isRatating)
                {
                    m_isRatating = true;
                }
            }
        }
        else
        {
            print("touch is not supported.");
            return;
        }

        if (m_isRatating)
        {
            float yRotation = m_nSpeedRatation * Time.deltaTime;
            if (m_nTotalAngle >= 360)
            {
                m_isRatating = false;
                m_nTotalAngle = 0;
            }
            m_nTotalAngle += yRotation;
            m_objRatation.transform.Rotate(0, yRotation, 0);
        }
    }

    void OnGUI()
    {
        if (GUILayout.RepeatButton("Enable/Disable MulitTouch(" + Input.multiTouchEnabled.ToString() + ")"))
        {
            Input.multiTouchEnabled = !Input.multiTouchEnabled;
        }
        if (GUILayout.RepeatButton("Enable/Disable simulateMouseWithTouches(" + Input.simulateMouseWithTouches.ToString() + ")"))
        {
            Input.simulateMouseWithTouches = !Input.simulateMouseWithTouches;
        }

        for (int i = 0; i < nMaxSelectedSize; ++i)
        {
            GUILayout.Label("Index(" + i + "):" + m_strSelectedGameObject[i].ToString());
        }
    }
}

重力加速器

當咱們垂直正對手機(手機屏幕對着咱們的臉)的時候,重力什麼怎麼樣呢?它有哪些方向,以及在每一個方向上的加速度是多少呢?
如今的手機或者pad通常都能對三個方向的力進行採集,分別是X,Y和Z。X的正方向水平向左,Y的正方向垂直向上,Z的正方向面向本身。爲了能更形象的說明這些問題,我簡單的畫了一個圖,下圖爲咱們垂直正對手機時候的重力加速圖:
這裏寫圖片描述
上圖中的兩個圓都表示的是兩個3D球體的前視圖。由上圖看,當咱們垂直正對手機時候,中間的藍色球體受到了來自地球-9.8米/秒的二次方加速度,那麼這時候咱們訪問Input.acceleration.y的時候,其值就是一個接近-9.8的值,其餘軸上都趨近於0。code

在Unity中訪問重力加速器的信息

重力加速器的信息被放在了UnityEngine.Input中。具體函數或字段見下表:orm

函數名 做用
acceleration 存放當前3個軸上感應到的加速度
accelerationEvents 在上一幀期間Unity引擎採集到的全部重力加速器信息(每一個方向上的加速度和時間增量)
accelerationEventCount 在上一幀期間Unity引擎採集到的全部重力加速度的次數

重力加速器示例

本示例就一個功能,咱們在場景中放一個Cube,當手機向指定方向偏轉時,Cube就向指定方向移動。示例代碼以下:htm

public class AccInputTest : MonoBehaviour {

    private float speed = 1.5f;
    //控制信息的打印時間
    private float fInterval = 1000;
    private float fCurTime = 0;
    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
        Vector3 dir = Vector3.zero;

        //unity的X軸的正方向是向左的
        dir.x = -Input.acceleration.x;
        dir.y = Input.acceleration.y;
        dir.z = 0;

        if (fCurTime >= fInterval)
        {
            Debug.Log("X:" + Input.acceleration.x + "    Y:" + Input.acceleration.y + "    Z:" + Input.acceleration.z);
            fCurTime = 0;
        }

        dir *= Time.deltaTime;
        fCurTime += Time.deltaTime;

        transform.Translate (dir * speed);
    }
}

虛擬鍵盤

在遊戲中咱們點擊輸入框(NGUI或Unity自帶控件)都會自動彈出虛擬鍵盤,固然咱們也能夠手動的彈出虛擬鍵盤,下面主要介紹如何手動的彈出鍵盤。鍵盤的操做被Unity放在了UnityEngine.TouchScreenKeyboard中。鍵盤的操做很是簡單,下面以一個簡單的示例來講明如何打開一個虛擬鍵盤,以及獲取輸入的數據。在一個腳本里的OnGUI函數中輸入以下代碼:

void OnGUI()
    {
        TouchScreenKeyboard.hideInput = true;
        if (GUILayout.Button ("KeyBoard:ASCIICapable")) {
            keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.ASCIICapable, false, false, false, false);
        }
        if (GUILayout.Button ("KeyBoard:Default")) {
            keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.Default, false, false, false, false);
        }
        if (GUILayout.Button ("KeyBoard:EmailAddress")) {
            keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.EmailAddress, false, false, false, false);
        }
        if (GUILayout.Button ("KeyBoard:NamePhonePad")) {
            keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.NamePhonePad, false, false, false, false);
        }
        if (GUILayout.Button ("KeyBoard:NumberPad")) {
            keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.NumberPad, false, false, false, false);
        }
        if (GUILayout.Button ("KeyBoard:NumbersAndPunctuation")) {
            keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.NumbersAndPunctuation, false, false, false, false);
        }
        if (GUILayout.Button ("KeyBoard:PhonePad")) {
            keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.PhonePad, false, false, false, false);
        }
        if (GUILayout.Button ("KeyBoard:URL")) {
            keyboard = TouchScreenKeyboard.Open("", TouchScreenKeyboardType.URL, false, false, false, false);
        }

        GUILayout.Label("");

        if (keyboard != null) {
            GUILayout.Label (keyboard.text);
        } else {
            GUILayout.Label ("keyboard is null.");
        }
    }

其餘輸入

Ps:在移動平臺的輸入中,Unity還爲咱們提供了諸如:位置,指南針,陀螺儀等設備的信息輸入。在這裏就不在詳述了,詳情參見官方文檔

傳統的輸入

像鼠標,鍵盤,操做杆和手柄這樣的輸入設備。如今暫且將其定義爲傳統的輸入設備,以便區分前面的移動平臺的輸入。在Unity中還爲咱們抽象出來一個叫作虛擬軸或虛擬按鈕的概念出來,在下面將分別介紹這兩種(實際上是一種,後者是由前者虛擬出來的)輸入方式。

鼠標,鍵盤,控制桿,手柄

因爲操做杆和手柄沒有設備,就不作介紹了,它跟其餘的操做是同樣的。

鍵盤
函數 |做用
---|----
GetKey|獲取鍵盤指定鍵是否按下(只要按下就是True擡起就是False)
GetKeyDown|獲取鍵盤指定鍵是否按下(按下那一刻是True)
GetKeyUp|獲取鍵盤指定鍵是否按下(彈起那一刻是True)
anyKey|是否按住了「任意鍵」(只要按下就是True擡起就是False)
anyKeyDown|是按下了「任意鍵」(按下那一刻是True)
對應的按鍵枚舉參見KeyCode

鼠標
函數| 做用
---|---
GetMouseButton| 獲取鼠標指定鍵是否按下(只要按下就是True擡起就是False)
GetMouseButtonDown|獲取鼠標指定鍵是否按下(按下那一刻是True)
GetMouseButtonUp|獲取鼠標指定鍵是否彈起(彈起那一刻是True)
注:0對應於鼠標左鍵,1對應於與鼠標右鍵,2對應於鼠標中鍵。

雖然上面的函數可以直接獲取到指定鍵是否按下,可是咱們通常不會直接這麼使用。使用Untiy提供的虛擬軸和按鍵能更靈活的控制咱們的輸入。好比我能夠將空格定義攻擊鍵,也能夠隨時改變這個鍵。虛擬軸還有一個好處,就是咱們能夠同時接受多輸入,好比我能夠接受鍵盤的空格做爲攻擊,也可使用操做杆或手柄上的一個鍵做爲攻擊鍵,由於咱們獲取的虛擬軸或按鈕都是同樣(「Fire1」)的。這裏可能說的有點抽象,很差懂,下面我會經過一個例子來講明這些。

虛擬控制軸(Virtual Axes)

虛擬軸的編輯

這裏寫圖片描述
下面對每一個參數簡單的說明,在看說明時對應下圖一塊兒看。圖以下:
這裏寫圖片描述

參數名 做用
Name 虛擬軸的名字(獲取虛擬軸時就須要傳入這個名字)
Descriptive Name 正方向上的控制鍵的描述信息
Descriptive Negative Name 反方向上的控制鍵的描述信息
Negative Button 主控制鍵反方向上對應的控制鍵
Positive Button 主控制鍵正方向上對應的控制鍵
Alt Negative Button 副控制鍵反方向上對應的控制鍵
Alt Positive Button 副控制鍵正方向上對應的控制鍵
Gravity 向中間值歸位時的速度
Dead 中間值的閾值,就是小於這個值則被定義爲是中間值了
Sensitivity 向目標歸位時的速度
Snap 是否須要平滑,若是沒有的話那麼就只有-1,0(中間值),1這三個值
Invert 將上面的正反方向顛倒
Type 使用那些輸入控制鍵,通常使用鼠標和鍵盤,若是你開發的是使用操做杆的那麼就是操做杆做爲輸入控制
Axis 抱歉不能理解
Joy Num 抱歉不能理解

相關函數
函數名|做用
----|---
GetAxis|獲取指定軸上當前採集的值,範圍爲[-1,1]
GetAxixRaw|獲取指定軸上當前採集的值,這個函數獲取的是沒有平滑過渡的值,也就是隻有-1,0,1這三個值
GetButton|獲取指定虛擬按鈕是否按下,當按下的是否爲True,談起的是否爲:False
GetButtonDown|獲取指定虛擬按鈕是否按下,當按下那一刻爲True
GetButtonUp|獲取指定虛擬按鈕是否擡起,當擡起那一刻爲True

虛擬軸或按鈕的示例

此示例主要實現2功能:

  1. 實現一個Cube在場景中先後左右的走動,經過獲取「Horizontal」和「Vertical」兩個虛擬軸來控制
  2. 實現一個Cube在場景中的旋轉,經過自定義的控制軸「Rotation」實現,「Rotation」咱們經過鼠標右鍵和鍵盤的空格鍵來控制。
    示例代碼以下:
public class AxesTest : MonoBehaviour {

    private float m_nSpeed = 5.0f;
    private bool m_isRotating = false;
    private float m_nRotationSpeed = 30.0f;
    private float m_nCurRotationAngle = 0;
    private const float m_nMaxAngle = 360;

    // Update is called once per frame
    void Update () {
        if (Input.GetButtonDown("Rotation") && !m_isRotating)
        {
            m_isRotating = true;
        }

        if (m_isRotating)
        {
            float nRotation = Time.deltaTime * m_nRotationSpeed;
            transform.Rotate(0, nRotation, 0);
            m_nCurRotationAngle += nRotation;
        }

        if (m_nCurRotationAngle >= m_nMaxAngle)
        {
            m_nCurRotationAngle = 0;
            m_isRotating = false;
        }

        float nXDeltaDistance = Input.GetAxis("Horizontal") * m_nSpeed * Time.deltaTime;
        float nYDeltaDistance = Input.GetAxis("Vertical") * m_nSpeed * Time.deltaTime;        
        if (nXDeltaDistance.Equals(0) && nYDeltaDistance.Equals(0))
            return;

        print("X:" + Input.GetAxis("Horizontal").ToString() + "   Y:" + Input.GetAxis("Vertical").ToString());
        transform.Translate(-nXDeltaDistance, nYDeltaDistance, 0);

    }
}

總結

Unity將其主要的輸入都放到了UnityEngine.Input類中,內部檢查或採集到輸入信息就將其結果放入Input中的對應字段,用於表示輸入的狀態。輸入大體分爲兩類,一個是移動平臺的輸入,像觸摸,虛擬鍵盤,重力加速感應器,羅盤,陀螺儀,GPS(位置)等,另外一類是傳統的輸入,像鍵盤,鼠標,操做杆和手柄等。

參考文獻

Unity官方文檔1:http://docs.unity3d.com/Manual/Input.html
Unity官方文檔2:http://docs.unity3d.com/ScriptReference/Input.html

相關文章
相關標籤/搜索