[英]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.