Unity集成Leap Motion

2023-11-17

转载自:http://www.cocoachina.com/game/20150716/12625.html  

演示视频文章最后

如果你已经熟悉编程的概念,理解并在C#语言方面有一定的经验,并且对面向对象编程思想和设计概念有所熟悉。如果你了解3D图像学和向量数学知识。不妨来看看吧~本文使用Unity 5.1~文中涉及的所有代码也能在旧版引擎上编译通过。

Leap Motion是什么?

在一只手上有29根骨头,29个关节,123根韧带,48根神经,30根动脉,复杂吧!还得乘以2,Leap Motion已经能够非常逼真的进行模拟了。Leap Motion感知你移动的双手,让你以一种新的方式与电脑交互,它以1毫米的100分之1的精度追踪你的10根手指,这大大超过现有的运动控制技术的敏感度,这就是为什么你可以在1英寸的立方体空间内画出微型杰作的原因。

QQ截图20150716113814.jpg

Leap Motion设置和Unity 集成

首先,你需要下载Leap Motion SDK,大家可以到developer.leapmotion.com 网站下载最新的版本,本文使用的是DK v.2.2.6.29154,下载完后,继续安装运行时,这个SDK支持所有的平台和语言,鼓励大家去了解下这些平台和语言。为了达成集成到Unity 中的目标,还需要下载Leap Motion Unity Core Assets v2.3.1。

假定你已经下载安装了Unity 5,下一步就是从Asset Store中获得Leap Motion Unity Core Assets 这个包,本文中用的是2.3.1版本。

QQ截图20150716113928.jpg

图2.Leap Motion Core Assets

下载安装完这个包后,我们就可以开始创建一个简单的场景,并且开始学习如何使用这些资源,并且将它们扩展到适合我们的要求。

QQ截图20150716114030.png

图3.Leap Motion在Project视图中的结构

继续创建一个空的Unity 工程,并且导入Leap Motion Core Assets包,当导入完后,项目的目录结构为上图所示。

Leap Motion Core Assets

在Project窗口里,你最该注意的是Leap Motion文件夹,这个文件夹包含的OVR是Leap Motion与Oculus Rift 虚拟现实头戴式设备相结合的资源,这个在以后会涉及到。你应该花时间学习每个文件夹内的结构,更重要的是内容。其中最主要的一个核心资源是Hand Controller,这个是允许你和Leap Motion设备交互的主要预制体,它作为锚点将你的双手渲染到场景中。

QQ截图20150716114128.jpg

图4.Hand Controller属性面板

Hand Controller 预制体有一个Hand Controller 脚本附加在上面,这样就允许了你和设备的交互。看一看检视面板里面的一些属性,你会发现那里有两个关于手的属性合作来在场景中渲染出真正的手部模型,并且那里有两个物理模型,这些是碰撞,这样设计的好处是你能创建你自己的手部模型,并且用在控制器里来查看效果,并且可以自定义手势等等。

注意:Unity 和Leap Motion 都是使用的米制系统,但是有些区别:Unity 的是以米为单位,Leap Motion用的是毫米,不是什么大问题,但是当你测量坐标的时候需要知道。

另一个关键属性是Hand Movement Scale 向量,缩放值越大,设备覆盖的物理世界范围越大,你需要查看文档来找到一个合适的数值来适应你当前的应用。Hand Movement Scale向量是用来在不改变模型大小的前提下改变双手移动的范围。

放置Hand Controller物体在场景中是重要的。如上所述,这是锚点的位置,因此,摄像机应该和Hand Controller在同一区域,在我们的示例场景中,将Hand Controller放置在(0,-3,3)处,确保摄像机在(0,0,-3)处,看一下坐标下并且看一下组件是如何在3D空间中呈现的,下面是图示:

QQ截图20150716114213.jpg

图5.可以看到Camera及Hand Controller位置

换句话说,你需要将Hand Controller放在摄像机前面,并且相对于摄像机往下一定数值范围内,这里没有魔法数值,你只需尝试适合你的数值即可。

到此,你已经将所有基础的部件结合起来了,并且场景可以运行测试Leap Motion的效果了。

去试试吧,如果你正确的安装了所有的软件组件,你将会在场景中看到你的双手。

下一步

你能在场景中看到双手的运动的事实是:通过提供的资源执行大量的任务,但是在现实中,想让事情变得更有趣,你将需要能够和环境交互,改变或调整场景中的东西。

为了说明这具体的一点,我们创建几个GameObject,我们将了解如何与GameObject实现一些基本的交互,我们将让一个立方体悬浮在空气中,我们想通过选择其他Cubes的颜色来改变这个Cube的颜色。

为了场景的简单起见,我们会放置3个立方体来代表取色盘,第一个是红色的,第二个是蓝色的,第三个是橘黄色的。你可以选择任何颜色,我们需要将立方体放置的有点规律,不然会让用户感到困惑。

将四个立方体这样放:

  • 没颜色的(0,1,3)

  • 红的: (3,-1,3)

  • 蓝的: (0,-1,3)

  • 橘黄色的: (-3,-1,3)

注意它们都在Hand Controller游戏物体Y轴的上面。但是在z轴它们在一个水平线上,你可以调整这些数字如果你喜欢的话,只要这些立方体在Hand Controller的检测范围之内就好。

下一步就是创建一个帮助我们与立方体交互的脚本,起名为scriptCubeInteraction.cs:

using UnityEngine;
using System.Collections;
public class CubeInteraction : MonoBehaviour {
   public Color c;
   public static Color selectedColor;
   public bool selectable = false;
   void OnTriggerEnter(Collider c)
   {
      if (c.gameObject.transform.parent.name.Equals("index"))
      {
         if (this.selectable)
         {
            CubeInteraction.selectedColor = this.c;
            this.transform.Rotate(Vector3.up, 33);
            return;
         }
         transform.gameObject.GetComponent().material.color = CubeInteraction.selectedColor;
      }
   }
}

正如你所看到的,这些代码不是很复杂,但是他的确帮助我们实现了我们想要做到的,这三个变量分别表示物体的颜色,物体所选择的颜色,物体是否为可以选择。

逻辑的核心在OnTriggerEnter(Colliderc) 函数内,我们检查与可选择物体的碰撞对象是不是食指,如果是,我们设置为该颜色。

另一个好主意是,我们设计这么一种交互,当食指与可选择颜色的立方体产生碰撞的后,让它旋转33度,这样我们能更直观的看出交互效果。

还是用同样的函数,在这个特别的例子里,我们获得立方体的Renderer组件,并设置他的材质颜色为我们所选择的颜色。

运行场景

下面是上述设置的截屏:

QQ截图20150716114330.jpg

图6.使用左手运行Demo

你可以看到我的左手在截屏中,我的右手在用鼠标点击开始截屏。下面是选择蓝色的截图:

QQ截图20150716114412.jpg

图7.选中蓝色立方体

最后将选中的蓝色应用到可变颜色的Cube上:

QQ截图20150716114452.jpg

图8.将蓝色应用到可变颜色的立方体上

移动物体是怎样的呢?

看到这里,你可能会觉得这好酷啊,但是如果还想实现与3D场景更进一步的交互,会不会更让人激动呢?例如说,你想捡起一个物体,并且将它移动到其他地方。如果想让它实现,我们就得写更多的代码。扩展我们的例子,我们将实现一个可以让我们捡起并移动立方体的项目。

抓起一个指定的物体由GrabMyCube.cs实现:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using Leap;
public class GrabMyCube : MonoBehaviour {
   public GameObject cubePrefab;
   public HandController hc;
   private HandModel hm;
   public Text lblNoDeviceDetected;
   public Text lblLeftHandPosition;
   public Text lblLeftHandRotation;
   public Text lblRightHandPosition;
   public Text lblRightHandRotation;
   // Use this for initialization
   void Start()
   {
      hc.GetLeapController().EnableGesture(Gesture.GestureType.TYPECIRCLE);
      hc.GetLeapController().EnableGesture(Gesture.GestureType.TYPESWIPE);
      hc.GetLeapController().EnableGesture(Gesture.GestureType.TYPE_SCREEN_TAP);
   }
  
   private GameObject cube = null;
   // Update is called once per frame
   Frame currentFrame;
   Frame lastFrame = null;
   Frame thisFrame = null;
   long difference = 0;
   void Update()
   {
      this.currentFrame = hc.GetFrame();
      GestureList gestures = this.currentFrame.Gestures();
      foreach (Gesture g in gestures)
      {
         Debug.Log(g.Type);
  
         if (g.Type == Gesture.GestureType.TYPECIRCLE)
         {
            // create the cube ...
            if (this.cube == null)
            {
               this.cube = GameObject.Instantiate(this.cubePrefab,
                                                  this.cubePrefab.transform.position,
                                                  this.cubePrefab.transform.rotation) as GameObject;
            }
         }
         if (g.Type == Gesture.GestureType.TYPESWIPE)
         {
            if (this.cube != null)
            {
               Destroy(this.cube);
               this.cube = null;
            }
         }
      }
  
      foreach (var h in hc.GetFrame().Hands)
      {
         if (h.IsRight)
         {
            this.lblRightHandPosition.text = string.Format("Right Hand Position: {0}", h.PalmPosition.ToUnity());
            this.lblRightHandRotation.text = string.Format("Right Hand Rotation: ", h.Direction.Pitch, h.Direction.Yaw, h.Direction.Roll);
  
            if (this.cube != null)
               this.cube.transform.rotation = Quaternion.EulerRotation(h.Direction.Pitch, h.Direction.Yaw, h.Direction.Roll);
  
            foreach (var f in h.Fingers)
            {
               if (f.Type() == Finger.FingerType.TYPE_INDEX)
               {
                  // this code converts the tip position from leap motion to unity world position
                  Leap.Vector position = f.TipPosition;
                  Vector3 unityPosition = position.ToUnityScaled(false);
                  Vector3 worldPosition = hc.transform.TransformPoint(unityPosition);
  
                  //string msg = string.Format("Finger ID:{0} Finger Type: {1} Tip Position: {2}", f.Id, f.Type(), worldPosition);
                  //Debug.Log(msg);
               }
            }
  
         }
         if (h.IsLeft)
         {
            this.lblLeftHandPosition.text = string.Format("Left Hand Position: {0}", h.PalmPosition.ToUnity());
            this.lblLeftHandRotation.text = string.Format("Left Hand Rotation: ", h.Direction.Pitch, h.Direction.Yaw, h.Direction.Roll);
  
            if (this.cube != null)
               this.cube.transform.rotation = Quaternion.EulerRotation(h.Direction.Pitch, h.Direction.Yaw, h.Direction.Roll);
         }  
      }  
   }
}

这个脚本里实现好几个功能,我将指出最重要的部分,剩下的大家自己摸索,例如,我不会涉及讲解UI界面方面的代码等等。你可以看看别人写的一些关于新的UGUI的系列博文。

我们定义了一个Hand Controller对象hc,这里就引用了Hand Controller对象,我们就可以在此脚本中调用此对象中的功能,第一件事是,我们需要用HandController对象注册手势,这在Start()方法中完成,这里有一些预先定义好的手势,所以我们将使用其中的一些,在这个示例中,我们注册了食指转圈,扫动,屏幕轻触手势类型。

我们还定义了两个GameObject变量,名为cubePrefab和cube,cubePrefab是我们引用的一个代表我们的立方体的预制体,这个预制体有对应材质和其他一些组件附加其上。

让我们看看Update()函数,这是所有魔法发生的地方,这也许会有点疑惑,但是你马上会了解它,我们在这里查找手势类型为typecircle,这将实例出一个我们预先制作好的名为cubePrefab的预制体,所以,第一件事是将当前帧对象传递到Hand Controller对象,一个帧对象包含了所有有关手部运动的信息,下一步是获得由传感器检测到的所有手势并储存为一个列表。

下一步我们将循环遍历每一个手势,并检测它的类型,如果我们检测到CIRCLE手势,我们就检查,我们是否已经实例化了我们的立方预制体,如果没有,实例化它,如何下一个手势类型是SWIPE,这将销毁我们实例化的预制体。

下一个循环基本上遍历检测完所有的手,检测它是左手还是右手,基于哪只手在执行特定的操作,在这个例子里,我们只是获得手的位置和旋转,并且根据手部的旋转来旋转我们实例化的立方体,没什么奇怪的。




本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity集成Leap Motion 的相关文章

  • Unity集成Leap Motion

    转载自 http www cocoachina com game 20150716 12625 html 演示视频文章最后 如果你已经熟悉编程的概念 理解并在C 语言方面有一定的经验 并且对面向对象编程思想和设计概念有所熟悉 如果你了解3D
  • 关于Albedo贴图、颜色贴图、Metallic 贴图、Specular贴图、法线贴图、视差贴图、凹凸贴图、Height Map高度贴图、AO 贴图Occlusion 贴图、Emission 贴图等

    在学习unity的过程中 被各种贴图弄得晕头转向 为了弄清楚各种贴图 查询了很多资料 粗略的整理如下 只要耐心看完 对贴图的基本用法基本上就没问题了 1 Albedo 贴图 可以看做是Diffuse颜色贴图 Albedo 反照率 贴图 用于
  • Unity UGUI的RawImage(原始图片)组件的介绍及使用

    Unity UGUI的RawImage 原始图片 组件的介绍及使用 1 什么是RawImage组件 RawImage是Unity UGUI中的一个组件 用于显示原始图片 与Image组件不同 RawImage可以直接显示原始图片的像素数据
  • MoCaPose:在宽松服装中实现动作捕捉

    动作姿态是人类个体活动和互动的基本信息来源 采集人们的动作信息能实现了解 分析日常生活等功能 尽管在宽松服装上可以使用IMU实现动作捕捉 但由于需要将大量IMU并将其节点牢固 精确地固定在特定的身体位置 因此并不适合许多现实生活中的应用 这
  • Unity的C#编程教程_52_类 Class 详解及应用练习(一)

    文章目录 C Classes for Behaviours Custom Classes 1 Custom Classes 2 Serialized Custom Class RPG Item Database Example 3 When
  • URP——后期处理特效

    通用渲染管道 URP 包括一个后处理效果的集成实现 如果使用URP 则不需要为后期处理效果安装额外的包 URP与Post Processing Stack v2包不兼容 URP使用体积框架进行后期处理效果 下面的图片显示了一个URP场景有没
  • unity中通过touch旋转、放大和缩小物体以及滑动方向的判断

    unity中通过touch旋转 放大和缩小物体以及滑动方向的判断这个需求在游戏开发中也是非常频繁 话不多说直接上代码 using System Collections using System Collections Generic usi
  • Unity3D中通过代码修改子物体层级的顺序

    今天有个同事问我如何在程序中修改子物体的层级关系来改变遮挡关系 我给他敲出来一句代码 UI的层级关系是通过渲染表现出来的 在canvas下的物体 排序越靠前的越先被渲染 这样一来就会 被后来渲染的遮挡 总结一下有三句代码是修改子物体的层级的
  • Unity中的单元测试

    我知道的单元测试有两种方法 1 从Unity的AssetStore窗口下载UnityTestTools 已下架了 2 使用TestRuner 2018 2 5以上版本有 我用的是2018 2 7 TestRuner的用法 操作窗口 Wind
  • Unity Cinemachine插件学习笔记,实现单目标和多目标之间切换

    Cinemachine在2017版中正式加入 结合Timeline可以轻松的制作出一下相机动画 相比Unity自带的标准相机 这个Cinemachine插件可操作的变量更多 不同虚拟相机 用来控制相机的 可以平滑转换等 具体可以参考上篇 U
  • Unity3D 碰撞器和触发器

    对于碰撞器和触发器经常忘记用法 这次主要记录下以便于能够复习用 1 碰撞器 发生条件 1 碰撞的双方中一定至少要有一个Rigidbody存在 并且碰撞双方必须都要有碰撞体组件 2 碰撞双方若只有一个有刚体 那么那个刚体一定要处于运动的状态下
  • Unity编辑器界面概述

    了解界面 如果您对编辑器界面没有非常地了解 那么请花一些时间查看并熟悉 Editor 编辑器 界面 Editor 主窗口由选项卡式窗口组成 这些窗口可重新排列 因此 Editor 的外观可能因项目或者开发者而异 具体取决于个人偏好 Wind
  • Unity编辑器扩展——进度条显示通用方法

    在我们使用Unity编辑器扩展做一些批处理的工具时 通常会需要显示一个进度条 这样不会让Unity一直卡住不动 使得使用者不知道当前的进展 那么如何显示进度条呢 涉及的相关API有 EditorUtility ClearProgressBa
  • 【Unity3d】Animator和Animation组件使用注意事项

    一 Animator一般用于人物动画控制 特点是动画是持续的 可能有动作切换 Animation一般用于间断性的动画的控制 比如一个场景特效的播放 只播放一次就完了 二 实测Animation速度比Animator快10 左右 内存占用没测
  • unity 读取和写入Excel中文出现乱码解决方法

    在编辑器中读取和写入中文一切正常 发布出来只要是中文就会出现乱码 解决方法 将C Program Files Unity Editor Data Mono lib mono unity 目录下的I18N dll和I18N CJK dll复制
  • Unity3D 官方文档 平台特殊化之Standalone和多显示器的处理

    版本 unity 5 6 语言 C 总起 Standalone 我一眼看下去的理解就是PC机平台 官方文档中说该平台指的是Mac Windows和Linux 这篇文章主要讲的是Standalone平台下的设置 通过点击菜单栏的File gt
  • Unity3D如何修改Button显示的文字以及深入了解Button组件

    在创建了一个Button后 结构如图 先仔细观察一下Button的Inspector视图 发现其中竟然有一个叫Button的脚本组件 新建脚本 代码如下 并将该脚本绑定给Canvas组件 using UnityEngine UI using
  • Input.GetAxis _ Unity3d

    Input GetAxis 获取轴 static function GetAxis axisName string float Description描述 Returns the value of the virtual axis iden
  • [Unity XLua]热更新XLua入门(一)-基础篇

    Aladdin XLua 前言 前段时间腾讯开源了一个内部热更框架XLua在Unity开发群里引起一阵热议 也受到广大开发者的热捧 然后我当然也抱着好奇的心去学习学习 后面也会将扩展之后的工程放在git上 大家一起学习交流 在此感谢XLua
  • unity dots jobSystem 记录

    Looking for a way to get started writing safe multithreaded code Learn the principles behind our Job System and how it w

随机推荐

  • Jenkins之Maven的配置

    Jenkins之Maven配置与项目集成 1 Maven集成 1 1 环境准备 1 2 Jenkins的web界面配置 1 3 安装maven插件 1 Maven集成 在Jenkins上发布Java项目时需要使用Maven来进行构建打包 G
  • LLVM是如何编译指令的

    本文将会通过一条指令在LLVM中的不同阶段 从源程序语言中的语义结构到成为机器二进制码来研究LLVM的工作原理 本文不会介绍LLVM是如何工作的 这需要理解LLVM的设计以及code以及各种细节 输入代码 我们从一段C代码开始探险 如下 i
  • kali Linux-2020.3 火狐浏览器改为中文

    1 打开右上角菜单栏 进行下图操作 2 更改语言这里 支持下拉框选择 如果没有中文选项 进行搜索下载 图中为以更新中文后的 英文状态下位置应该是一样的 3 在搜索语言里找到中文 点击添加 添加成功后会提示 应用并重新打开 点击这个选项重新打
  • Linux调试、跟踪命令:strace/ltrace、ldd、objdump、nm、strings

    一 strace ltrace 1 1 功能 strace Trace system calls and signals 跟踪进程的系统调用或信号产生的情况 ltrace A library call tracer 跟踪进程调用库函数的情况
  • Android上面的百度地图使用步骤

    1 下载百度地图移动版API Android 开发包 要在Android应用中使用百度地图API 就需要在工程中引用百度地图API开发包 这个开发包包含两个文件 baidumapapi jar和libBMapApiEngine so 下载地
  • Swagger 的使用

    文章目录 Swagger 的使用 前言 Swagger 简介 SpringBoot 集成 Swagger 2 x SpringBoot 集成 Swagger 3 0 配置 Swagger 配置文档信息 配置扫描接口 配置功能是否启动 配置
  • scrapy,scrapy-redis显示:什么都没爬取到:Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)

    解决方法一 问题 刚开始爬取有 但是后面都是Crawled 0 pages at 0 pages min scraped 0 items at 0 items min 解决 可能是里面没有设置 yield scrapy Request do
  • 在Ubuntu 14.04.2 LTS上安装Qt

    Qt是一个跨平台的应用程序框架 广泛用于开发具有GUI界面的应用软件以及命令行工具 几乎所有操作系统都可以使用Qt 如Windows Mac OS X Android等 用于开发Qt应用程序的主要编程语言是C 但是可以使用诸如Python
  • 1.12mc java几,1.12 - 崩溃解答 - MC百科社群 - MC百科

    游戏是在mcbbs上找的the disguiser Mohist 崩溃报告 WARNING coremods are present ForgelinPlugin Forgelin 1 8 3 jar Inventory Tweaks Co
  • AcWing 1875. 贝茜的报复 枚举+dfs

    AcWing 1875 贝茜的报复 打卡 这题的dfs太妙了 include
  • window.history.go(-1)和window.location.go(-1)的区别

    为什么80 的码农都做不了架构师 gt gt gt window history go 1 是返回上一页 window location go 1 是刷新上一页 弹出子页面
  • 安装redis 管理工具、redis扩展服务

    1 查看php 的版本 还有这种方式 在网站根目录下新建一个简单的phpinfo文件 输入phpinfo函数 在浏览器中打开 2 PHP 7 3 4 安装 Redis 4 0 Windows系统 直接在浏览器中搜索下载 Redis 4 0
  • svg怎么转换成png格式?

    svg怎么转换成png格式 在我们日常的工作和学习当中 会使用各种格式的图片 在使用的过程中 我们会发现每种格式的图片所具备的特点是完全不同的 像svg就是一种矢量图 一系列由线连接的点的实体 一般在用在图像 文字以及标志设计等场景 从它的
  • 按键精准控制步进电机起保停,正反转(Arduino+TB6600驱动器)

    精准控制步进电机起保停 正反转 Arduino TB6600驱动器 步进电机和驱动器相关的资料 https pan baidu com s 1udb4MyEOXk4CTO7TKRHj6w 提取码 fuea 步进电机 TB6600驱动器 接线
  • 数据准备(data preparation)

    数据预处理及数据准备 提到数据预处理 首先不得不考虑到pandas库 链接pandas 文章目录 数据预处理及数据准备 数据准备前置知识 数据处理步骤 数据预处理实战 二 使用步骤 1 读入数据 创建一个关于所有变量的分散矩阵 数据准备前置
  • 常用函数和代码

    1 加载数据函数 数据保存 import numpy as np import dill dill dump session GAT pkl dill load session t20 pkl save path data Enron gr
  • pytest测试报告Allure - 动态生成标题生成功能、添加用例失败截图

    一 动态生成标题 默认 allure 报告上的测试用例标题不设置就是用例名称 其可读性不高 当结合 pytest mark parametrize 参数化完成数据驱动时 如标题写死 其可读性也不高 那如果希望标题可以动态的生成 采取的方案是
  • 赋值、浅拷贝与深拷贝

    一 数据类型 数据分为基本数据类型 String Number Boolean Null Undefined Symbol 和引用数据类型 基本数据类型 基本数据类型存储在栈内存中 引用数据类型 存储的是该对象在栈中引用 即引用地址 真实的
  • csv数据筛选 matlab_在matlab中从CSV文件中读取特定列

    I am trying to read a CSV file in matlab I just want to read the second column but the code below prints out everything
  • Unity集成Leap Motion

    转载自 http www cocoachina com game 20150716 12625 html 演示视频文章最后 如果你已经熟悉编程的概念 理解并在C 语言方面有一定的经验 并且对面向对象编程思想和设计概念有所熟悉 如果你了解3D