2017-02-10 126 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