前言
最近有新成员加入本团队,为了方便其开发HoloLens1 / HoloLens2,将不定时更新HoloLens相关开发相关内容。
软件需求:
HoloLens 1:VS2017 + Unity2017;HoloLens 2:VS2019 + Unity2019;
1.安装VS2017 / VS2019,HoloLens 1安装Win10 SDK 17134或者17763,HoloLens2要求至少18362;相关安装与配置请参考博文.
2.Unity2017 / Unity2019,安装UWP平台;
注:如果使用的软件为VS2019和Unity2019来开发HoloLens1,可参考HoloLens2的开发过程,修改MRTK的配置文件为HoloLens1即可!可参考博文1,博文2.
以HoloLens结合Vuforia在二维码上显示一个立方体Cube,并实现点击变色为例。
一、Vuforia
1.注册及获取LicenseKey
1.目前世界上主流的AR SDK提供厂商,国外的主要是Vuforia、Metaio,国内的主要是EasyAR。
2.进入Vuforia官网后,点击注册,注册免费账号,登录;
3.在官网Develop-License Manager一栏中,点击“Get Development Key”按钮进行获取LicenseKey;
4.填入当前项目名称,同意协议,执行获取LicenseKey;
5.点击创建的LicenseKey进入到详细内容界面,如图所示,点击复制,保存在本地Txt中便于后期使用;
2.创建项目数据库
1.在官网Develop-Target Manager一栏中,点击“Add Datebase”;
2.进入刚刚新建的Database,点击Add Target,上传识别图;
注意识别图需要特征明显,上传后网站会显示照片特征质量,质量较低的建议重新上传;
1)上图中Type为识别类型,依次为图片,立方体,圆柱体和3D物体,识别图选择类型1;
2)选择对应图片;
3)查看图片详细信息,其像素宽度即为该数值;
4)数据库中该识别图的名称;
点击添加,如下图,勾选后点击下载
二、新建Unity工程,添加Vuforia
1.首先切换平台,“File-Build Settings-UWP”,点击switch Platform;再点击“Player Settings-Other Settings-Scripting Backend”,IL2CPP切换为.NET;点击Add Open Scene,UWP平台的相关配置如图所示。
2.选择菜单栏“Assets-Import Packages-Custom Packages”,选择刚刚下载的文件,点击Import;
3.右键新建Vuforia-AR Camera,删除默认的Main Camera;选中AR Camera,将World Center Mode选为Camera,点击Open Vuforia configuration,填写保存在本地的LicenseKey,相关配置如下;
在Database中取消默认的数据库,激活导入的用户数据库;
4.在面板中右键添加“Vuforia-Image”,选中该ImageTarget,在右侧修改其识别图;
尤其要注意:Image的Scale需要和实际打印的识别图大小保持一致,如这里我识别的图像大小为8cm,所以在Unity中填写Scale为0.08,否则将引起虚拟对象的漂移,与预想位置不符;
5.在面板中选中ImageTarget,右键添加“3D Object->Cube”,可以修改Cube的大小比例;
3.为了方便观察,可以修改Cube的材质。在Assets中右键创建材质,更改材质球颜色,然后拖到Cube上,可以观察到Cube颜色改变。
三、添加脚本,实现点击控制
1.在Assets中新建Script文件夹,在其中新建三个脚本,脚本内容如下。
1)GazeGesture.cs
using UnityEngine;
using UnityEngine.XR.WSA.Input;
public class GazeGesture : MonoBehaviour
{
public static GazeGesture Instance { get; private set; }
// 保存当前凝视的物体;
public GameObject FocusedObject { get; private set; }
GestureRecognizer recognizer;
// Use this for initialization
void Start()
{
Instance = this;
// 用来检测手势;
recognizer = new GestureRecognizer();
recognizer.TappedEvent += (source, tapCount, ray) =>
{
// 向凝视的物体和父物体发送OnSelect消息;
if (FocusedObject != null)
{
FocusedObject.SendMessageUpwards("OnSelect");
}
};
recognizer.StartCapturingGestures();
}
// Update is called once per frame
void Update()
{
// Figure out which hologram is focused this frame.
GameObject oldFocusObject = FocusedObject;
//根据头的位置的方向发射射线;
// Do a raycast into the world based on the user's
// head position and orientation.
var headPosition = Camera.main.transform.position;
var gazeDirection = Camera.main.transform.forward;
RaycastHit hitInfo;
if (Physics.Raycast(headPosition, gazeDirection, out hitInfo))
{
// If the raycast hit a hologram, use that as the focused object.
FocusedObject = hitInfo.collider.gameObject;
}
else
{
// If the raycast did not hit a hologram, clear the focused object.
FocusedObject = null;
}
// If the focused object changed this frame,
// start detecting fresh gestures again.
if (FocusedObject != oldFocusObject)
{
recognizer.CancelGestures();
recognizer.StartCapturingGestures();
}
}
}
2)Cursor.cs
using UnityEngine;
public class Cursor : MonoBehaviour
{
private MeshRenderer meshRenderer;
// Use this for initialization 初始化时候调用
void Start()
{
// Grab the mesh renderer that's on the same object as this script.
// 获取 meshRenderer
meshRenderer = this.gameObject.GetComponentInChildren<MeshRenderer>();
}
// Update is called once per frame 每一帧都会自动更新
void Update()
{
// 根据用户头的位置和朝向发射射线;
// head position and orientation.
var headPosition = Camera.main.transform.position;//头部位置是相机的位置;
var gazeDirection = Camera.main.transform.forward;//头部朝向;
RaycastHit hitInfo;//用于存储射线碰撞到的第一个对象信息。需要提前创建这个对象。
if (Physics.Raycast(headPosition, gazeDirection, out hitInfo))//Physics.Raycast此静态函数用于在场景中发射一条可以喝碰撞器碰撞的射线
{
// 如果射线碰到了hologram,显示光标;
meshRenderer.enabled = true;// Move the cursor to the point where the raycast hit.把光标移到射线碰撞的地方;
this.transform.position = hitInfo.point;//将光标移到射线碰撞位置;将光标与hologram的表面平行;
this.transform.rotation = Quaternion.FromToRotation(Vector3.up, hitInfo.normal);
}
else
{
//如果没有碰到物体隐藏光标;
meshRenderer.enabled = false;
}
}
}
3)执行脚本(CubeScript):
using System.Collections;
using UnityEngine;
public class CubeScript : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public void OnSelect()
{
//随机变换物体颜色
gameObject.GetComponent<MeshRenderer>().material.color = new Color(Random.Range(0, 255) / 255f, Random.Range(0, 255) / 255f, Random.Range(0, 255) / 255f);
}
}
2.在面板中分别新建一个空物体和一个Sphere,空物体命名为Manager,Sphere的比例修改为(0.01,0.01,0.01).
3.将GazeGesture脚本拖到Manager上,Cursor脚本拖到Sphere上,执行脚本CubeScript拖至Cube上.
4.选中作为视线的Sphere,在面板中做出以下修改(两种方法任选一种):
1)修改Layer为Ignore Raycast;
2)取下勾选Sphere Collider,添加Rigidbody组件;
如果不进行以上处理,读者可自行尝试可能出现的小问题
四、工程发布与部署
1.工程发布
1.在Unity的player setting中找到Publishing Settings,在Capabilities中勾选:Internet Client、WebCam、Microphone、SpatialPreception;在XR Settings中设置如下。
2.点击Build,选择发布文件夹,生成VS2017解决方案.
2.工程部署
1.双击打开生成目录中的VS工程,选中“Package.appxmanifest”,右键选择“查看代码”,修改以下内容;如果出现提示打不开,多尝试几次即可。
2.选择Debug,x86平台,用USB连接HoloLens与PC,选择Device,“调试-开始执行(不调试)”,点击运行。
3.第一次连接HoloLens部署工程需要输入PIN码,根据提示,在HoloLens的设置中,选择安全-开发者选项,点击Pair,在PC输入HoloLens中出现的6位PIN码即可。
4.部署成功后,在HoloLens端打开程序,扫描二维码即可看到Cube,点击Cube颜色改变!
总结
以上是HoloLens1结合Vuforia开发的简单Demo以及程序发布与部署流程,欢迎批评指正!