gpt4 book ai didi

c# - 我可以使用 Input.GetAxis ("Horizontal") 来检测 Unity 中的水平滑动吗?

转载 作者:太空宇宙 更新时间:2023-11-03 15:08:42 24 4
gpt4 key购买 nike

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

Input.GetAxis("Horizo​​ntal") 会根据您是向左还是向右滑动,给出一个介于 -1 和 1 之间的范围。

如果我将 Debug.Log(Input.GetAxis("Horizo​​ntal")) 添加到 void update() 它会在每次滑动时多次打印出轴范围/按键。

如何获取单个(第一个)值 Input.GetAxis("Horizo​​ntal") 返回值?

我想做这样的事情:

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

这是否可能或是否有实现水平滑动的方法?

最佳答案

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

一种方法是使用 Reactive Extensions。您可以下载响应式扩展的统一兼容版本 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 上获得。 .

关于c# - 我可以使用 Input.GetAxis ("Horizontal") 来检测 Unity 中的水平滑动吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42150941/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com