【问题标题】:Hololens Navigation using tap and hold gesture bug?Hololens 导航使用点击并按住手势错误?
【发布时间】:2017-07-26 22:02:13
【问题描述】:

使用来自HoloToolkit 资产和实现代码的 InputManager 预制件,用户可以点击并按住给定对象,然后向左或向右移动(沿 x 平面)以沿 Y 轴或上下(沿 y 平面)在 X 轴上旋转对象。

但是似乎有一个错误。如果用户的视线从物体上移开,则旋转立即停止,直到用户的视线回到物体上。这是预期的功能吗?如果是这样,如何保留通过导航手势更改的当前对象并允许它继续被操纵,直到用户的手离开 FOV 或用户释放点击并按住手势?

目标是利用点击并按住手势,但不要求用户在旋转对象的整个过程中将目光锁定在对象上。这对于小的或形状不规则的物体来说是相当困难的。

实现代码:

[Tooltip("Controls speed of rotation.")]
public float RotationSensitivity = 2.0f;

private float rotationFactorX, rotationFactorY;

public void OnNavigationStarted(NavigationEventData eventData)
{
    Debug.Log("Navigation started");
}
public void OnNavigationUpdated(NavigationEventData eventData)
{
    rotationFactorX = eventData.CumulativeDelta.x * RotationSensitivity;

    rotationFactorY = eventData.CumulativeDelta.y * RotationSensitivity;

    //control structure to prevent dual axis movement
    if (System.Math.Abs(eventData.CumulativeDelta.x) > System.Math.Abs(eventData.CumulativeDelta.y))
    {
        //rotate focusedObject along Y-axis
        transform.Rotate(new Vector3(0, -1 * rotationFactorX, 0));
    }
    else
    {
        //rotate focusedObject along X-axis
        transform.Rotate(new Vector3(-1 * rotationFactorY, 0, 0));
    }
}
public void OnNavigationCompleted(NavigationEventData eventData)
{
    Debug.Log("Navigation completed");
}
public void OnNavigationCanceled(NavigationEventData eventData)
{
    Debug.Log("Navigation canceled");
}

【问题讨论】:

    标签: c# unity3d gesture hololens


    【解决方案1】:

    你需要调用这些方法:

        NavigationRecognizer = new GestureRecognizer();
        NavigationRecognizer.SetRecognizableGestures(GestureSettings.Tap);
        NavigationRecognizer.TappedEvent += NavigationRecognizer_TappedEvent;
        ResetGestureRecognizers();
    

    这是针对被点击的事件,但执行其他 gestures 很简单,只需为它们添加事件回调并在 SetRecognizableGestures() 调用上使用 | OR 选择器。例如

        NavigationRecognizer.SetRecognizableGestures(GestureSettings.Tap | GestureSettings.NavigationX);
    

    【讨论】:

    • 我很困惑。点击是否也注册点击并按住?您是否使用 OR (|) 将点按并按住和 X 轴导航合二为一?
    • @jtth TapHold 是分开的,如果您查看 GestureSettings 枚举,您会看到其所有可能的值。您甚至可以设置一个程序来识别所有这些(尽管我很确定Navigation_NavigationRails_Manipultation 都是互斥的,因为它们都依赖于相同的手势,但解释略有不同。而且是的,在这种情况下,我使用按位或来组合两种手势类型(在这种情况下,点击和 nav-x)。它不会将手势组合成一个事件,它说“我对这些类型的事件感兴趣...”
    • 您仍然需要NavigationRecognizer.NavigationEvent += ... 才能获得回调。 (X、Y、Z都由同一个事件处理)
    • @jtth 应该在您的问题中的同一脚本中,在 Start()Awake() 内,假设它是附加到游戏对象的 MonoBehavior。如果不是,那么您将需要一种方法来对其进行初始化(即答案代码位于某个函数中,Init() 或您从某些 MonoBehavior 的 Start()Awake() 调用的构造函数)。
    • 好的,想通了。在导航开始时清除堆栈InputManager.Instance.ClearModalInputStack();,将用户正在使用导航手势的对象推送到堆栈上,InputManager.Instance.PushModalInputHandler(gameObject); 然后在导航完成或取消时,将其从堆栈中弹出。 InputManager.Instance.PopModalInputHandler(); 将此添加到我自己的实现脚本中。这是可能的,因为 InputManager 预制件为我创建了堆栈,因此它变得相当简单。
    【解决方案2】:

    Draco18 的答案更安全,但这个解决方案也很有效,因为 InputManager 预制件为我们实现了一个堆栈。

    在导航开始时,清除堆栈并将正在“导航”的对象压入堆栈,

    InputManager.Instance.ClearModalInputStack(); InputManager.Instance.PushModalInputHandler(gameObject);

    在导航完成或取消时,将其从堆栈中弹出。 InputManager.Instance.PopModalInputHandler();

    将此添加到您自己的实现脚本中,无需调整 InputManager 上任何预先存在的脚本。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-05
      相关资源
      最近更新 更多