首页 资讯 硬件 视频 视界娱乐 开发者中心 论坛

LeapMotion开发(四)检测工具

36评论 分享:QQ 微信 微博
Date:2016-09-22 07:19 来源: 未知
摘要:使用探测器,需要添加它到场景中作为游戏对象的一个组件,他让大部分传感器放置脚本在对象相关功能上。例如,在拇指对象自身上放置一个探测器去检测拇指的状态。你可以使用
HandAttachments 预设体从附件模块中分离可视化代表的担忧和游戏逻辑中的物理交互。

LeapMotion开发(四)检测工具

一、使用探测器

使用探测器,需要添加它到场景中作为游戏对象的一个组件,他让大部分传感器放置脚本在对象相关功能上。例如,在拇指对象自身上放置一个探测器去检测拇指的状态。你可以使用

HandAttachments 预设体从附件模块中分离可视化代表的担忧和游戏逻辑中的物理交互。

 

一旦探测器被添加到场景中,你可以在Unity面板中设置他的属性。探测器属性不同,但是大都包含以下内容:

l Period –周期决定探测器检测手状态的频率

l Hand Model–哪一个手被探测器看到。如果你放置探测器在一个手的模型上,那么探测器将会自动寻找手的父物体。否则,你可以手动设置手物体。

l On and Off values –打开值设置该点哪个探测器开启;关闭值设置它再次关闭。一般的开关值之间应该有一点小区别防止当追踪值正好在阀值上时,探测器从开关状态之间跳跃。

l Show Gizmos –设置是否探测器绘画图形调试辅助。当在Unity编辑器中也启用时,仍然只显示图形。当在相同的手上有多个探测器时,关闭单个探测器图形可能会对你有帮助。

二、标准Unity事件

当一个探测器开启 (activates)或者关闭(deactivates)时,它分派标准Unity事件。你可以在Unity检查面板中保留这些事件,Unity游戏对象或者它的组件,或者自己写脚本。主要探测器事件是OnActivate 和OnDeactivate。一些探测器分派额外的事件。

三、组合探测器

你可以组合多个探测器使用DetectorLogicGate 脚本去创建更复杂的行为。一个逻辑门采用任何数量的其他探测器作为输入和输出单独bool值。这是探测器对象类型,因此它也分派OnActivate和OnDeactivate 事件。你可以设置逻辑门为“与”逻辑门(所有输入输出都为true)或者“或”逻辑门(如果任何输入为true那么输出为true)。你也可以否定输出,配置逻辑门为“非与”或“非或”逻辑门。

 

逻辑门自身是一个探测器,因此你可以保留多个逻辑门去创建任意复杂逻辑。但是,如果你有超过两个逻辑门,那么你应该考虑写一个脚本包含这个逻辑是否更易于维护。如果你连接多个逻辑门,不要勾选“Add All Sibling Detectors”选项并且手动的拖拽合适的探测器到逻辑门列表。

四、使用探测器附件

HandAttachments 预设上含有HandAttachments 脚本公开的两种方法, Activate() 和 Deactivate()你可以直接保留到探测器的分配事件。当Activate()被调用时AttachmentController 脚本启用子游戏对象的附件控制器,当Deactivate()被调用时禁用它们。

因此,你可以使用探测器去开启或者关闭对象附加到手。

 

五、探测器框架

以下的创意集合说明如何在应用程序中使用探测器来实现行为和交互。

拇指向上(Thumb’s Up)

检测“拇指向上”使用ExtendedFingerDetector 去检查拇指是唯一伸出的手指并且FingerDirectionDetector 去检查探测当拇指指向上方。组合这些探测器和“与”类型逻辑门:

l ExtendedFingerDetector – 配置组件因此拇指必须被伸出而其他手指不伸出。

l FingerDirectionDetector – 配置组件因此:

· Finger Name = TYPE_THUMB

· Pointing Direction = (0, 1, 0)

· Pointing Type = Relative To World

· On and Off angles: set as desired

 

l DetectorLogicGate –设置逻辑门类型为“与”类型并且保留事件检测分派到对象或者组件应该影响到拇指向上。

你必须放置一起这些组件在拇指变换的HandAttachment (或者任何地方适合在真正HandModel )。

六、抓取

在Unity中抓取可能是相当复杂并且有许多边界情况需要被纳入总体考虑。当你想要去拾取对象,事情变得相当复杂,对象也有刚体,你要像其他和手的碰撞。这是LeapMotion创建交互引擎就有挑战性的原因。对于简单的例子,当手应该拾取或者释放一个对象时你可以使用检测器去确定并些Unity脚本做对象运动或是重设父物体。

下面的例子使用ProximityDetector 去选择对象拾取;PinchDetector 去触发拾取和释放,和添加一个简单自定义脚本并且分离对象到手的拾取点。

添加下列组件到HandAttachment的PinchPoint游戏对象 :

ProximityDetector –添加任何对象符合捡到目标对象列表。(您也可以使用标记或层识别潜在的目标。

PinchDetector –默认设置工作,你也可以调整Activate 和Deactivate 拾取距离属性去调整多远或者多近拇指和手指必须拾取或者释放对象。

添加一个新的脚本组件命名“Pickup”使用下列代码:

using UnityEngine;

using Leap.Unity;

 

public class Pickup : MonoBehaviour {

 

 GameObject _target;

 

 public void setTarget(GameObject target) {

   if (_target == null) {

     _target = target;

   }

 }

 

public void pickupTarget() {

   if (_target) {

     StartCoroutine(changeParent());

     Rigidbody rb = _target.gameObject.GetComponent<Rigidbody>();

     if(rb != null) {

       rb.isKinematic = true;

     }

   }

 }

 

 //Avoids object jumping when passing from hand to hand.

 IEnumerator changeParent() {

   yield return null;

   if(_target != null)

       _target.transform.parent = transform;

 }

 

 public void releaseTarget() {

   if (_target && _target.activeInHierarchy) {

     if (_target.transform.parent == transform) { //Only reset if we are still the parent

       Rigidbody rb = _target.gameObject.GetComponent<Rigidbody>();

       if (rb != null) {

         rb.isKinematic = false;

       }

       _target.transform.parent = null;

     }

     _target = null;

   }

 }

 

 public void clearTarget(){

   _target = null;

 }

}

最后,设置探测器事件派发器去调用Pickup 脚本方法:

· PinchDetector.OnActivate() -> Pickup.pickupTarget()

· PinchDetector.OnDeactivate() -> Pickup.releaseTarget()

· ProximityDetector.OnDeactivate() -> Pickup.clearTarget()

· ProximityDetector.OnProximity(GameObject) -> Pickup.setTarget(GameObject)

这个脚本足以拾取游戏对象有或者没有刚体和徒手通过他们。去避免碰撞问题,该脚本转变刚体为运动(kinematic )当他们被拾取并当他们被释放时转变他们为非运动。

七、制作你自己的探测器

 

 

using UnityEngine;

using UnityEngine.Events;

using Leap;

using Leap.Unity;

 

  public class CustomDetector : Detector {

    public float Period = .1f; //seconds

    public float OnValue  = 1.0f;

    public float OffValue = 1.5f;

 

    private float gizmoSize = .1f;

    private IEnumerator watcherCoroutine;

 

    void Awake(){

      watcherCoroutine = watcher();

    }

 

    void OnEnable () {

        StopCoroutine(watcherCoroutine);

        StartCoroutine(watcherCoroutine);

    }

 

    void OnDisable () {

      StopCoroutine(watcherCoroutine);

    }

 

    IEnumerator watcher(){

      float watchedValue = 20;

      while(true){

          //Your logic to compute or check the current watchedValue goes here

 

        if(watchedValue > OffValue){

          Activate();

        }

        if(watchedValue < OnValue){

          Deactivate();

        }

        yield return new WaitForSeconds(Period);

      }

    }

 

    #if UNITY_EDITOR

    void OnDrawGizmos(){

      if(IsActive){

        Gizmos.color = OnColor;

      } else {

        Gizmos.color = OffColor;

      }

      Gizmos.DrawWireSphere(transform.position, gizmoSize, OnValue);

      Gizmos.color = LimitColor;

      Gizmos.DrawWireSphere(transform.position, gizmoSize, OffValue);

    }

    #endif

  }