Unity中觸摸和鼠標操作的幾個問題

關鍵點1:

在unity中touch事件同時也會觸發GetMouseButton事件,有時候可能會給你帶來方便,但是如果沒有意識到這個問題的話,也很可能給你帶來很大的麻煩。

關鍵點2:

觸摸操作也可以使用Input.GetAxis(“Mouse X”)(或”Mouse Y”,下同,略去不寫)來判斷指尖移動的距離,雖然這點很方便,但是這樣就帶來了另外兩個問題,見關鍵點3和4;

關鍵點3:

Input.GetAxis(“Mouse X”)取得的值與Input.GetTouch(0).deltaPosition的取值有一些細微但是很重要的差別:

  1. 如果使用鼠標操作,那麼Input.GetAxis對鼠標移動的取值方式表現的很正常,因爲不管是否點擊,鼠標始終存在,鼠標位置始終能夠正常獲取,Input.GetAxis(“Mouse X”)原本是爲鼠標設計的,取值方式是連續的;使用Input.GetTouch(0).deltaPosition無效,因爲沒有觸摸操作;
  2. 如果使用觸摸操作,再細分兩種情形:

    1. 如果使用if(Input.GetMouseButton(0))來作爲判斷是否按下的條件:
      那麼使用Input.GetAxis來獲取手指的移動就需要注意了,觸摸的手指是可以離開屏幕的,一旦手指離開屏幕,GetAxis(“Mouse X”)就不知所措了,只好記住離開前的手指位置,下一次手指再接觸的時候和這個位置對比(個人猜測GetAxis(“Mouse X”)是對比鼠標/觸摸點位置的方法來取得的)。例如手指從屏幕的左邊拿開,然後再觸摸屏幕的右邊,那麼取得的x位置會是一個很大的正值。這就是個很大的問題,這個問題是GetMouseButton和GetAxis在使用手指觸摸的情況下配合上的不默契產生的。但是使用Input.GetTouch(0).deltaPosition就不會有這種現象,個人猜測可能是因爲deltaPosition是測量每一幀內的移動距離的方法吧。
    2. 如果使用 if(Input.touchCount>0&&Input.GetTouch(0).phase == TouchPhased.Moved)來做爲判斷是否按下的條件:
      使用Input.GetAxis(“Mouse X”),沒有任何問題;
      使用deltaPosition同樣沒有任何問題,因爲這就是爲觸摸操作而設計的。

關鍵點4:

實踐中發現在直觀感覺差不多的滑動過程(分別用鼠標拖動和手指拖動)中,Input.GetTouch(0).deltaPosition.x 的值總是比Input.GetAxis(“Mouse X”)取得的值要大很多,分析可能是手機屏幕dpi比較大的原因,因此在實踐中爲了獲取直觀感受差不多的旋轉速度,要分別調試旋轉加成係數。

總結

不要使用一條代碼判斷兩種情況,最好分開,做一個單選(可以使用Enum),要麼鼠標操作,要麼觸摸操作,分別使用最合適的判斷和函數,並分別調試旋轉加成係數

事件回顧

在寫一個慣性拖動旋轉的腳本的時候,爲在pc和Android平臺上都能使用(即用鼠標和觸摸都能控制),我使用瞭如下的判斷語句:

if(Input.GetMouseButton(0) || (Input.touchCount>0 && Input.GetTouch(0).phase == TouchPhase.Moved)

來判斷鼠標按下或者手指按下,並用Input.GetAxis(“Mouse X”)來獲取拖動的值,期望能夠一次判斷兩種情況,分別適應不同平臺的操作。在pc上使用鼠標操作沒有任何問題,但是在android上觸摸操作時出現了問題。經過多次測試並查閱資料,發現原來觸摸操作也可以觸發Input.GetMouseButton(0)的事件,這就引發了前述 關鍵點3第二條第一項中的問題。

附:慣性旋轉物體腳本:

using UnityEngine;
using System.Collections;
//操作方式
public enum ControlType{
mouseControl,
touchControl,
}
public class RotateTarget: MonoBehaviour
{
public ControlType controlType;
    public Transform rotTarget;

//旋轉速度加成係數
    public float rotSpeedScalar;
    private float currentSpeed = 0;

    void Update()
    {
        if (controlType==ControlType.mouseControl)
        {
            //鼠標操作
            if (Input.GetMouseButton(0))
            {
                    //拖動時速度
   //鼠標或手指在該幀移動的距離*deltaTime爲手指移動的速度,此處爲Input.GetAxis("Mouse X") / Time.deltaTime
   //不通幀率下lerp的第三個參數(即混合比例)也應根據幀率而不同--
   //考慮每秒2幀和每秒100幀的情況,如果此參數爲固定值,那麼在2幀的情況下,一秒後達到目標速度的0.75,而100幀的情況下,一秒後則基本約等於目標速度
                    currentSpeed = Mathf.Lerp(currentSpeed, Input.GetAxis("Mouse X") / Time.deltaTime,0.5f*Time.deltaTime);
            } else
            {
                //放開時速度
                currentSpeed = Mathf.Lerp(currentSpeed, 0, 0.5f*Time.deltaTime);
            }
        }
else if(controlType==ControlType.touchControl)
        {
            //觸摸操作
            if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved)
            {
//在安卓設備上也可以用Mouse X,根據實驗,touch[0].deltaPosition.x的值總是比Mouse X的值大很多,所以此處使用Mouse X
currentSpeed = Mathf.Lerp(currentSpeed, Input.GetAxis("Mouse X")/Time.deltaTime,0.5f*Time.deltaTime);
            } else
            {
                //放開時速度
                currentSpeed = Mathf.Lerp(currentSpeed, 0, 0.5f*Time.deltaTime);
            }
        }
        rotTarget.Rotate(Vector3.down, Time.deltaTime * currentSpeed * rotSpeedScalar);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章