目錄html
任何遊戲都應該提供給用戶交互的方式,能夠想象一個沒有任何交互的遊戲是什麼樣的。若是沒有輸入系統帶來的,用戶與遊戲的交互那麼遊戲將再也不是遊戲,由於玩家將不能進行任何操做,那還怎麼玩呢?Unity做爲一個號稱跨平臺性能最好的遊戲引擎,那麼它給咱們提供了哪些輸入呢?爲了可以更好的整理Unity的輸入系統,暫時將其分爲移動平臺的輸入和傳統的輸入。ide
在手機和pad上主要的輸入方式就是:觸摸,重力加速器,虛擬鍵盤等。Unity將這些操做都封裝到了UnityEngine.Input和UnityEngine.TouchScreenKeyboard這兩個類裏。函數
在UnityEngine.Input類中爲咱們提供了觸摸相關的函數,以及在UnityEngine命名空間中涉及到的類,相關函數和類以下表:性能
函數表:
|函數名 |做用
----|-----
multiTouchEnabled| 是否啓用多點觸摸
simulateMouseWithTouches| 啓用/禁用使用觸碰仿真鼠標的操做
touchCount| 在此幀中的觸摸數量
touches|在上一幀中的觸摸點(Touch)信息
touchSupported| 標示當前運行此程序的設備是否支持觸摸
GetTouch|根據觸摸點的索引獲取觸摸點的信息
類表:
類名 |做用
---|--
Touch| 觸摸點信息
TouchPhase| 觸摸點的狀態信息測試
此示例主要實現以下三個功能:this
示例代碼,以下: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
重力加速器的信息被放在了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」)的。這裏可能說的有點抽象,很差懂,下面我會經過一個例子來講明這些。
下面對每一個參數簡單的說明,在看說明時對應下圖一塊兒看。圖以下:
參數名 | 做用 |
---|---|
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功能:
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