繁体   English   中英

我可以使用Input.GetAxis(“ Horizo​​ntal”)来检测Unity中的水平滑动吗?

[英]Can I use Input.GetAxis(“Horizontal”) to detect a horizontal swipe in Unity?

我想检测水平滑动,以便用户可以向左或向右滑动以切换一堆游戏角色。 向左滑动1个可切换/显示前一个字符,向右滑动1个可切换/显示下一个字符。

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();
 }
}

这是可能的还是有办法实现水平滑动?

您遇到的问题是,在滑动过程中,在每个游戏周期内都会调用您的函数,而您的函数最终会被多次调用。 基本上,您希望有一种方法来过滤更新事件流并仅选择相关事件。

一种方法是使用Reactive Extensions 您可以在此处下载反应式扩展的统一版本。

完成此操作后,您将能够将单位输入转换为可观察的流 这是您可以执行的操作:

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;
    }
}

上面的脚本仅包含一个多维数据集,该多维数据集在检测到滑动时会短暂闪烁不同的颜色。

我的github上提供了上述示例的完整版本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM