天天看點

Unity3D技術之鍵盤、操縱杆和遊戲搖桿輸入實作詳解

輸入桌面

Unity 支援鍵盤、操縱杆和遊戲搖桿輸入。

可以在輸入管理器 (Input Manager) 中建立虛拟軸和按鈕,終端使用者可以在簡潔美觀的配置對話框中配置鍵盤。

Unity3D技術之鍵盤、操縱杆和遊戲搖桿輸入實作詳解

您可以設定操縱杆、搖桿、鍵盤和滑鼠,然後通過簡單的腳本界面通路所有設定。

在腳本中,所有虛拟軸都按照名稱通路。

在建立之時,所有工程都有以下預設的輸入軸:

1、 水準線 (Horizontal) 和垂直線 (Vertical) 映射至 w、a、s、d 和方向鍵。

2、Fire1、Fire2、Fire3 分别映射至 Control、Option (Alt) 和 Command 鍵。

3、 Mouse X 和 Mouse Y 映射至滑鼠移動增量。

4、 Window Shake X 和 Window Shake Y 對應視窗的移動。

添加新的輸入軸

如需添加新的虛拟軸,轉到編輯 (Edit)->工程設定 (Project Settings)->輸入 (Input) 菜單。也可在這裡更改每個軸的設定。

Unity3D技術之鍵盤、操縱杆和遊戲搖桿輸入實作詳解

每個軸可以對應操縱杆、滑鼠的兩個按鈕或兩個鍵盤按鍵。

名稱 (Name) 用來在腳本中檢查該軸的字元串名稱。 

描述名稱 (Descriptive Name) 配置 (Configuration) 對話框輸入頁籤中顯示的正名稱,用于獨立建構。 

描述負名稱 (Descriptive Negative Name) 配置 (Configuration) 對話框輸入頁籤中顯示的負名稱,用于獨立建構。 

負按鈕 (Negative Button) 用于在負方向移動軸。 

正按鈕 (Positive Button) 用于在正方向移動軸。 

備選負按鈕 (Negative Button) 用來在負方向移動軸的備選按鈕。 

備選正按鈕 (Alt Positive Button) 用來在正方向移動軸的備選按鈕。 

重力 (Gravity) 在沒有按任何按鈕時,軸下降到 0 的每秒機關速度。 

死亡 (Dead) 模拟死區的大小。所有在這個範圍内的模拟裝置值将映射為 0。 

靈敏度 (Sensitivity) 軸向目标值移動的每秒機關速度。該功能僅用于數位裝置。 

捕捉 (Snap) 如果啟用,按下相反方向的按鈕時,軸值将自動歸零。 

反向 (Invert) 如果啟用,按下負按鈕 (Negative Button) 将提供正值,反之亦然。 

類型 (Type) 控制此軸的輸入類型。 

軸 (Axis) 連接配接裝置的軸将控制這個軸。 

操縱杆 (Joy Num) 連接配接操縱杆将控制這個軸。 

這些設定可用來微調輸入的外觀和感覺。他們在編輯器均帶有工具提示。

使用腳本中的輸入軸

從像這樣的腳本,可以查詢目前狀态,如下所示:

value = Input.GetAxis (“Horizontal”);

軸值在 -1 到 1 之間。中間位置為 0。 這是在操縱杆輸入和鍵盤輸入的情況下。

但是,滑鼠增量和 Window Shake 增量是指滑鼠或視窗在最後一幀移動的距離。這意味着,當使用者快速移動滑鼠時,它可能大于 1 或小于 -1。

您可以建立多個名稱相同的軸。在獲得輸入軸時,絕對值最大的軸将被傳回。這使得為一種以上輸入裝置指定同一個軸名稱成為可能。例如,為鍵盤輸入建立 一個軸,并且為操縱杆建立另一根名稱相同的軸。如果使用者使用操縱杆,輸入将來自操縱杆,否則,輸入将來自鍵盤。有了這種方法,在編寫腳本時,您無需再考慮 輸入的來源。

按鈕名稱

要映射一個鍵到一個軸,您必須在檢視器中的正按鈕 (Positive Button) 或負按鈕 (Negative Button) 屬性中輸入按鍵名稱。

按鍵名稱遵循以下慣例:

1、 标準鍵: “a”、”b”、”c”、…

2、 數字鍵:”1〃、”2〃、”3〃、 …

3、 方向鍵:“上 (up)”、“下 (down)”、“左 (left)”、“右 (right)”

4、小鍵盤鍵:”[1]”、”[2]”、”[3]”、”[+]”、”[=]”

5、修改鍵:”right shift”、”left shift”、”right ctrl”、”left ctrl”、”right alt”、”left alt”、”right cmd”、”left cmd”

6、滑鼠按鈕:”mouse 0〃、”mouse 1〃、”mouse 2〃, …

7、 操縱杆按鈕(從任意操縱杆):”joystick button 0〃、”joystick button 1〃、”joystick button 2〃、 …

8、操縱杆按鈕(從指定操縱杆):”joystick 1 button 0〃、”joystick 1 button 1〃、”joystick 2 button 0〃、…

9、 特殊鍵:”backspace”、”tab”、”return”、”escape”、”space”、”delete”、”enter”、”insert”、”home”、”end”、”page up”、”page down”

10、 功能鍵:”f1〃、”f2〃、”f3〃、…

在腳本界面和檢視器中,用來識别按鍵的名稱是一樣的。

value = Input.GetKey (“a”);

移動輸入

在 iOS 和 Android 平台,輸入類别可以讓您通路觸摸屏、加速度計及地理/位置輸入。

通過iOS 鍵盤可提供移動裝置鍵盤通路。

多點觸控螢幕

iPhone 和 iPod Touch 裝置最多可同時追蹤螢幕的五個觸點。您可以通路 Input.touches 屬性數組,檢索最後一幀每個觸點的狀态。

Android 裝置對于追蹤的觸點數量沒有統一限制。相反,它根據裝置的而有所不同,某些老舊裝置可能是兩點,而最新的裝置可以到五點。每個觸點都以一個 Input.Touch 資料結構表示:

手指索引 (fingerId) 每次觸摸的唯一指數。 

位置 (position) 觸摸在螢幕中的位置。 

增量位置 (deltaPosition) 最後一幀以來的螢幕位置變化。 

增量時間 (deltaTime) 最後一次狀态變化以來的經過的時間。 

點選數 (tapCount) iPhone/iPad 螢幕可以分辨使用者的快速觸摸。這個計數器可以讓您知道使用者在不移動手指的情況下觸摸螢幕的次數。Android 裝置不會計算觸摸的次數,是以,這個字段始終為 1。 

階段 (phase) 描述所謂的觸摸“階段 (phase)” 或狀态。它有助于确定使用者是否剛開始觸摸,是否使用者移動手指,是否使用者剛剛擡起手指。 

階段主要分為以下幾個部分:

開始 (Began) 手指剛剛接觸螢幕。 

移動 (Moved) 手指在螢幕上移動。 

靜止 (Stationary) 手指觸摸螢幕,但自最後一幀以來并未移動。 

結束 (Ended) 手指離開螢幕,是觸控的最後一個階段。 

取消 (Canceled) 系統已取消觸控跟蹤,例如,使用者将裝置接觸面部或同時超過 5 個觸摸點。這是觸控的最後一個階段。 

下面是一個使用者輕觸螢幕即射出光線的腳本示例:

var particle : GameObject;

function Update () {

for (var touch : Touch in Input.touches) {

if (touch.phase == TouchPhase.Began) {

// Construct a ray from the current touch coordinates

var ray = Camera.main.ScreenPointToRay (touch.position);

if (Physics.Raycast (ray)) {

// Create a particle if hit

Instantiate (particle, transform.position, transform.rotation);

}

}

}

}

滑鼠模拟

除原生的觸摸支援以外,Unity iOS/Android 還提供滑鼠模拟。您可以使用标準輸入類中的滑鼠功能。

加速度計

在移動裝置移動的過程中,内置的加速度計報告在三維空間三個主要軸上的線性加速度改變。硬體将直接報告每根軸的加速度作為重力值。值為 1.0 代表所給出的軸的負載約為 +1g,而 -1.0 則代表 -1g。如果裝置垂直放置(Home 鍵位于下方)于身體正前方,那麼 X 軸在右邊是正值,Y 軸在上方是正值,Z 軸則在指向您本人的一方為正值。

可以通路 Input.acceleration 屬性,檢索加速度計值。 以下是使用加速度計移動對象的腳本示例:

var speed = 10.0;

function Update () {

var dir : Vector3 = Vector3.zero;

// we assume that the device is held parallel to the ground

// and the Home button is in the right hand

// remap the device acceleration axis to game coordinates:

// 1) XY plane of the device is mapped onto XZ plane

// 2) rotated 90 degrees around Y axis

dir.x = -Input.acceleration.y;

dir.z = Input.acceleration.x;

// clamp acceleration vector to the unit sphere

if (dir.sqrMagnitude > 1)

dir.Normalize();

// Make it move 10 meters per second instead of 10 meters per frame...

dir *= Time.deltaTime;

// Move object

transform.Translate (dir * speed);

}

低通過濾器

加速度計讀數可能被颠簸和噪音影響。在信号中應用低通濾波器有助于使其更平滑,并去除高頻噪音。

以下腳本展示了如何将低通濾波器應用到加速度計讀數:

var AccelerometerUpdateInterval : float = 1.0 / 60.0;

var LowPassKernelWidthInSeconds : float = 1.0;

private var LowPassFilterFactor : float = AccelerometerUpdateInterval / LowPassKernelWidthInSeconds; // tweakable

private var lowPassValue : Vector3 = Vector3.zero;

function Start () {

lowPassValue = Input.acceleration;

}

function LowPassFilterAccelerometer() : Vector3 {

lowPassValue = Mathf.Lerp(lowPassValue, Input.acceleration, LowPassFilterFactor);

return lowPassValue;

}

LowPassKernelWidthInSeconds 的值越大,過濾值在目前輸入樣本中彙集的速度越慢(反之亦然)。

在擷取加速度計讀數時,我希望它能盡可能精确,我該怎麼做?

讀取 Input.acceleration 變量并不等于采樣硬體。簡而言之,Unity 以 60Hz 的頻率采樣硬體,并将結果儲存到變量中。事實上,事情并非如此簡單 —— 在大量 CPU 負荷的情況下,加速度計采樣不 會以相同的時間間隔發生。是以,系統可能一幀報告兩個樣本,而下一幀又隻有一個樣本。

您可以通路加速度計在每幀執行的所有測量。以下代碼将舉例說明最後一幀收集的所有加速度計事件的簡單平均數:

var period : float = 0.0;

var acc : Vector3 = Vector3.zero;

for (var evnt : iPhoneAccelerationEvent in iPhoneInput.accelerationEvents) {

acc += evnt.acceleration * evnt.deltaTime;

period += evnt.deltaTime;

}

if (period > 0)

acc *= 1.0/period;

return acc;