2017-02-10 128 views
2

我想檢測一個水平滑動,這樣用戶可以向左或向右滑動來切換一組遊戲角色。 1左手滑動切換/顯示前一個字符,1右滑動切換/顯示下一個字符。我可以使用Input.GetAxis(「水平」)檢測Unity中的水平滑動嗎?

Input.GetAxis("Horizontal")會給我-1和1之間的範圍取決於如果你向左或向右滑動。

如果我將Debug.Log(Input.GetAxis("Horizontal"))添加到void update()它會在每次滑動/按鍵時多次打印軸範圍。

我怎樣才能得到一個(第一)值Input.GetAxis("Horizontal")回報?

我想要做這樣的事情:

void Update() { 
float swipe = Input.GetAxis("Horizontal"); 
if (swipe > 0) { 
    ToggleRight(); 
} else if (swipe < 0) { 
    ToggleLeft(); 
} 
} 

這是可能的,或者是有實現刷卡水平的方式?

回答

0

您遇到的問題是,你的功能得到每場比賽週期期間調用,而刷卡過程中,你的函數最終得到多次調用。基本上,你想有一種方法來過濾更新事件流,只選擇相關的事件。你能做到這

一種方式是通過使用無擴展。您可以下載反應式擴展的統一兼容版本here

一旦你這樣做了,你就可以將單位輸入轉換爲可觀察流。下面是你如何做到這一點:

using UnityEngine; 

// You'll need to include these namespaces. 
using UniRx; 
using System.Linq; 
using System; 

// This will be responsible for converting unity input 
// into a stream of events. 
public class SwipeListener : MonoBehaviour 
{ 
    // Rx Subjects allow you to create an observable stream of your 
    // own. You can push events to the stream by calling OnNext(). 
    private Subject<float> _subject; 

    // We'll expose the above stream via this property for a couple reasons. 
    // 1) If we exposed the subject directly, other code could push events to 
    //  our stream by calling OnNext(). Preventing that helps avoid bugs. 
    // 2) We'll be filtering the stream to avoid having too many swipe-events. 
    public IObservable<float> InputStream { get; private set; } 

    // Event values will be grouped by threes and averaged 
    // to smooth out noise. 
    [SerializeField] 
    private int _bufferCount = 3; 

    // Average displacement level below which no swipe event 
    // will be triggered. 
    [SerializeField] 
    private float _minimumThreshhold = 15; 

    // To prevent back-to-back swipe events. 
    [SerializeField] 
    private float _slidingTimeoutWindowSeconds = .25f; 

    private void Update() 
    { 
     // We push values to our stream by calling OnNext() on our 
     // Subject in each game step. 
     _subject.OnNext(GetInputValue()); 
    } 

    // Here is where we get the value that will be pushed into the stream. 
    // For this demonstration, I'm using the mouse-position. You could easily 
    // override this and return touch positions instead. 
    protected virtual float GetInputValue() 
    { 
     return Input.mousePosition.x; 
    } 

    public SwipeListener() 
    { 
     _subject = new Subject<float>(); 

     // This is where the real magic happens. IObservable supports many of the 
     // same LINQ operations as IEnumerable. 
     IObservable<float> filtered = _subject 

      // Convert stream of horizontal mouse positions into a stream of 
      // mouse speed values. 
      .Pairwise() 
      .Select(x => x.Current - x.Previous) 

      // Group events and average them to smooth out noise. The group size 
      // can be configured in the inspector. 
      .Buffer(_bufferCount) 
      .Select(x => x.Average()) 

      // Filter out events if the mouse was not moving quickly enough. This 
      // can be configured in the inspector. You'll want to play around with this. 
      .Where(x => Mathf.Abs(x) > _minimumThreshhold); 

     // Now we'll apply a sliding timeout window to throttle our stream. this 
     // will help prevent multiple back-to-back swipe events when you swipe once. 
     // I've split the event stream into two separate streams so we can throttle 
     // left and right swipes separately. This will help ensure that there isn't 
     // unnecessary lag when swiping left after having swiped right, or vice-versa. 

     TimeSpan seconds = TimeSpan.FromSeconds(_slidingTimeoutWindowSeconds); 
     IObservable<float> left = filtered 
      .Where(x => x < 0) 
      .Throttle(seconds); 

     IObservable<float> right = filtered 
      .Where(x => x > 0) 
      .Throttle(seconds); 

     // Now that we've throttled left and right swipes separately, we can merge 
     // them back into a single stream. 
     InputStream = left.Merge(right); 
    } 
} 

現在你所要做的就是編寫一個消耗上述腳本的腳本。這裏有一個如何做到這一點的例子:

using UnityEngine; 
using System.Collections; 
using UniRx; 

[RequireComponent(typeof(MeshRenderer))] 
[RequireComponent(typeof(SwipeListener))] 
public class ColorFlasher : MonoBehaviour 
{ 
    [SerializeField] 
    private Material _left; 

    [SerializeField] 
    private Material _right; 

    private Material _normal; 

    [SerializeField] 
    private float _flashPeriod = .1f; 

    private MeshRenderer _meshRenderer; 

    private SwipeListener _inputListener; 

    void Start() 
    { 
     _meshRenderer = GetComponent<MeshRenderer>(); 
     _normal = _meshRenderer.material; 

     _inputListener = GetComponent<SwipeListener>(); 
     _inputListener.InputStream 
      .Subscribe(x => StartCoroutine(FlashColor(x))); 
     _inputListener.InputStream.Subscribe(x => Debug.Log(x)); 
    } 

    private IEnumerator FlashColor(float swipe) 
    { 
     Material material = _normal; 

     if (swipe > 0) 
      material = _right; 
     else if (swipe < 0) 
      material = _left; 

     _meshRenderer.material = material; 

     yield return new WaitForSeconds(_flashPeriod); 

     _meshRenderer.material = _normal; 
    } 
} 

上述腳本只是有閃爍不同顏色的簡要只要檢測到刷卡的立方體。

上面的例子中的一個完整的版本可以在on my github