使用Rx API计算鼠标拖动事件中的指针增量

时间:2017-09-12 00:49:09

标签: c# unity3d system.reactive

我尝试使用 Rx API创建游戏用户界面(UniRx具体),并且难以尝试摆脱全局状态变量。

UI有两个拖动手柄,您可以使用它们分别控制相机旋转和高度。我编写了以下代码来处理拖动事件:

Action<IPointerDragAware, Vector3> register = (button, direction) =>
{
    var events = button.OnDrag.Select(v => v.position);

    Observable.Zip(events, events.Skip(1))
        .Select(v => v[1] - v[0])
        .Select(v => Normalize(v, direction))
        .Subscribe(OnDrag)
        .AddTo(this);

    // I want to remove this hack.
    button.OnDragEnd
        .Subscribe(_ => _dragFinished = true)
        .AddTo(this);
};

register(RotateButton, Vector3.right);
register(MoveButton, Vector3.up);

private void OnDrag(Vector2 delta)
{
    // And this too...
    if (_dragFinished)
    {
        _dragFinished = false;
        return;
    }

    // Code to move camera around follows...
}

我需要 _dragFinished hack的原因是当我拖动一个按钮然后拖动另一个按钮时防止相机移动的峰值,因为当前代码只计算指针增量而不考虑它们是否来自是否采取相同的连续拖动动作。

我尝试比较时间戳,但将 .Where 过滤器放到压缩的事件流中,使其挂起。可能我做错了什么,但我还是 Rx API的新手,所以我现在几乎被卡住了。

所以,如果有人能给我一些关于如何重写它以摆脱任何成员变量的提示,我会感激不尽?

谢谢!

2 个答案:

答案 0 :(得分:1)

var drags = button.OnDrag.Select(v => v.position);
var dragEnds = button.OnDragEnd;

drags.GroupByUntil(_ => true, _ => dragEnds)
     .SelectMany(b => b.ToList())
     .Where(i => i.Count == 2) //could be less, could be more...
     .Select(i => Normalize(i[1]-i[0], direction))
     .Subscribe(OnDrag)
     .AddTo(this);

GroupByUntil + SelectMany combo返回OnDragEnd事件之间的OnDrag事件列表。 假设按钮事件可观察性很热。

答案 1 :(得分:1)

对于一般解决方案,请参阅@ supertopi的上述答案。我设法通过以下代码使其工作,因为 UniRx 还不支持 GroupByUntil

var events = button.OnDrag.Select(v => v.position);

Observable
    .Zip(events, events.Skip(1))
    .TakeUntil(button.OnDragEnd)
    .RepeatSafe()
    .Select(i => Normalize(i[1] - i[0], direction))
    .Subscribe(MoveCamera)
    .AddTo(this);