參考資料:
Input
Input Manager
測試手把 :PS Analog gamepad
Script語言:C#
Unity 版本:3.4
Unity提供了3種輸入裝置可以使用,鍵盤、滑鼠、以及遊戲手把。
此篇紀錄在取得遊戲手把輸入時,所遇到的問題以及解決方案。
首先,要先開啟Unity提供的Input Manager(Edit->Project Setting->Input Manager),就可以看到Unity所提供預設的按鈕事件。這邊也可以自訂自己想要用的按鈕,只需要更改size欄位的數值即可,Unity就會利用最後一組按鈕做為參考值,複製一份新的按鈕設定。官方稱這些設定為虛擬軸(Virtual Axes)或是虛擬按鈕(Virtual Button)。
Unity提供預設兩組水平輸入以及垂直輸入,一組是提供給鍵盤訊息使用,另一組是設定給遊戲手把使用。不過這兩個輸入是使用相同的名稱。這邊推測,是要讓寫script的時候,不需要根據裝置而另外寫輸入判斷或是數值取得。如果是這樣設計的話,那算是還蠻方便的功能。
為了測試Unity是否能正確接收到遊戲手把的訊息,就寫了底下的測試程式來測試結果。
using UnityEngine;
using System.Collections;
public class InputTest : MonoBehaviour {
protected float m_JoyX = 0.0f;
protected float m_JoyY = 0.0f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update ()
{
m_JoyX = Input.GetAxis("Horizontal");
m_JoyY = Input.GetAxis("Vertical");
Debug.Log("Get Horizontal input from Joystick = " + m_JoyX.ToString());
Debug.Log("GetVertical input from Joystick = " + m_JoyY.ToString());
}
}
測試結果:
測試結果還不錯,用手把或是鍵盤都可以接收到訊息。
不過這種作法有個缺點,就是Update()是每個frame都會更新一次,所以就會一直收到沒按下按鍵時的資料。
因此需要做一些判斷式來確定按鍵有按下時,才取得所需要的按鍵值。
所以更改後的程式碼如下:
using UnityEngine;
using System.Collections;
public class InputTest : MonoBehaviour {
protected float m_JoyX = 0.0f;
protected float m_JoyY = 0.0f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update ()
{
m_JoyX = Input.GetAxis("Horizontal");
m_JoyY = Input.GetAxis("Vertical");
if( Input.GetButton("Horizontal") )
{
Debug.Log("Get Horizontal input from Joystick = " + m_JoyX.ToString());
}else if(Input.GetButton("Vertical")) {
Debug.Log("GetVertical input from Joystick = " + m_JoyY.ToString());
}
if( Input.GetKey(KeyCode.JoystickButton11) ){
print("Get Joystick Button 0");
}
//Debug.Log("Get Horizontal input from Joystick = " + m_JoyX.ToString());
}
}
測試結果如下圖:
結果,手把訊息沒進來?!
之後試過很多方法,例如把按鍵名稱改成不同的名稱,也是一樣沒有接收到手把方向鍵按下的訊息。
這邊的測試就繞了很久,後來索性把手把方向鍵是否有輸入這件事情,改成判定軸向值是否有值(也就是不為0)。結果就可正常的在手把方向鍵按下時,才取得所要的數值。
原本不曉得是不是Unity的bug還是限制,畢竟這一塊的說明,官方文件沒有講得很清楚。而提供的按鍵訊息也只有上、下、左、右四個鍵盤按鍵而已。目前推測是,因為手把輸入的Type為Joystick Axis,然後軸並沒有所謂的按鈕觀念,所以這邊就無法用
Input.GetButton()來取得是否有按下這個動作。
改判定軸向是否有值後,的確解決上述的問題
,但與鍵盤要同時共用的時候,卻又出了問題。
就是因為手把跟鍵盤是使用相同的虛擬按鈕名稱,所以取得的軸向資料有時並不是手把輸入的,反而會是鍵盤輸入的。
因此目前為了解決這問題,就是把手把輸入跟鍵盤輸入的虛擬按鈕名稱改成不一樣,這樣就可以確定輸入的資料是確切的來自於鍵盤還是手把。雖然在實作遊戲的時候會很不方便(因為要另外把手把輸入拆出來判斷),但是如果透過繼承跟多型,是可以讓實作遊戲變方便。至於如何繼承跟多型的部分就之後另外開個主題紀錄了(因為目前還在測試中XD)。
最後可以同時使用鍵盤與遊戲手把輸入,但也不會互相影響的方式如下:
(
或是在Input Manager內使用相同的熱鍵名稱也行。之前測試不過可能是有設定沒弄好。 2011/08/31)
using UnityEngine;
using System.Collections;
public class InputTest : MonoBehaviour {
protected float m_JoyX = 0.0f;
protected float m_JoyY = 0.0f;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update ()
{
m_JoyX = Input.GetAxis("Horizontal_Joy");
m_JoyY = Input.GetAxis("Vertical_Joy");
if( Input.GetButton("Horizontal") )
{
print("Get Horizontal input from keyboard = " + Input.GetAxis("Horizontal").ToString());
}else if( Input.GetButton("Vertical") ){
print("Get Vertical input from keyboard = " + Input.GetAxis("Vertical").ToString());
}else if( Input.GetButton("Horizontal_Joy") ){//m_JoyX != 0.0f ){
Debug.Log("GetHorizontal input from Joystick = " + m_JoyX.ToString());
}else if( m_JoyY != 0.0f ){
Debug.Log("GetVertical input from Joystick = " + m_JoyY.ToString());
}
if( Input.GetKey(KeyCode.JoystickButton11) ){
print("Get Joystick Button 0");
}
}
}
測試結果如下:
輸出結果也就很符合目前的需求嚕。
不過此時Joystick Y軸上為負值,所以有需要用Y軸上為正值時,需把Inverse選項打勾,就可以了。
PS.1.官方有註明鍵盤跟手把的軸向值介於-1到1。滑鼠部分則不一定在此區間。
PS.2.在測試過程中發現,把Dead設為0.00001以下時,在手把方向鍵未按下時,
Input.GetAxis()取得到的座標值其實是不為零的。
因此如果使用別的手把時,發現官方的預設值無法讓未按下方向鍵時取得的值為零的情況下,只要把Dead參數改大就好。反之如果按下按鍵後,收到的值為零,就把Dead參數改小(大於0,小於1)就可以了。
官方對於Dead的說明為,當收到的按鍵數值低於Dead的值的時候,就會強制設為0。
請問一下
ReplyDelete上面第一篇的script您是放在哪裡呢?
是放在car裡面 啟動之後consloe就會自動跳出訊息嗎?
不好意思,您指的上一篇的意思是?
ReplyDelete我沒記錯得話,是把script掛在要接收事件的物件上。
如您提到的car物件要接收鍵盤事件,就把寫好的script加到car物件上就可以了。
大大您好 方便提問問題嗎
ReplyDelete可以..請說。不好意思,現在才看到。
Delete