Unity 中的坐标系统
Windows Mixed Reality 支持各种体验级别的应用,既支持仅限方向的应用和坐姿级别应用,也支持房间级别应用。 在 HoloLens 上,你可以进一步构建世界级别应用,让用户可以步行 5 米以上的距离,探索建筑的整个平面甚至更远的地方。
在 Unity 中构建混合现实体验的第一步,是理解坐标系并选择你的应用的目标体验级别。
构建“仅限方向”或“坐立空间规模”的体验
命名空间:UnityEngine.XR
类型:XRDevice
若要构建“仅限方向”或“坐姿级别”体验,需将 Unity 的跟踪空间类型设置为“静止”。 静止跟踪空间会将 Unity 的世界坐标系统设置为跟踪静止参照系。 在“静止”跟踪模式下,启动应用时,放置在编辑器中相机默认位置(前向为 -Z)正前方的内容将出现在用户面前。
XRDevice.SetTrackingSpaceType(TrackingSpaceType.Stationary);
命名空间:UnityEngine.XR
类型:InputTracking
对于纯粹的“仅限方向”体验,例如 360 度视频查看器(其中头部位置更新会破坏视觉效果),可以将 XR.InputTracking.disablePositionalTracking 设置为 true:
InputTracking.disablePositionalTracking = true;
对于“坐立空间规模”体验,若要让用户稍后重新定位坐姿原点,可调用 XR.InputTracking.Recenter 方法:
InputTracking.Recenter();
创建一个“站立空间级别”或“房间级别”体验
命名空间:UnityEngine.XR
类型:XRDevice
对于“站立空间规模”或“房间规模”体验,需要将内容相对于地板放置。 可以使用空间阶段来判断用户的平面,空间阶段代表用户定义的平面原点和可选的房间边界,需要在第一次运行时进行设置。
为了确保 Unity 在地板级别使用其世界坐标系统进行操作,可以进行设置并测试 Unity 是否在使用 RoomScale 跟踪空间类型:
if (XRDevice.SetTrackingSpaceType(TrackingSpaceType.RoomScale))
{
// RoomScale mode was set successfully. App can now assume that y=0 in Unity world coordinate represents the floor.
}
else
{
// RoomScale mode was not set successfully. App cannot make assumptions about where the floor plane is.
}
- 如果 SetTrackingSpaceType 返回 true,则 Unity 已成功切换其世界坐标系统以跟踪场地参照系。
- 如果 SetTrackingSpaceType 返回 false,则表明 Unity 无法切换到场地参照系,原因可能是用户尚未在其环境中设置地板。 虽然返回 false 值并不常见,但如果场地设置在不同的房间,且设备移动到当前房间后用户没有设置新的场地,则可能会发生这种情况。
应用成功设置 RoomScale 跟踪空间类型后,平面上会显示放置在 y=0 平面上的内容。 (0, 0, 0) 处的原点将是用户在房间设置过程中站立的地板上的特定位置,其中 -Z 表示设置过程中面对的正前方。
命名空间:UnityEngine.Experimental.XR
类型:边界
在脚本代码中,你可以对 UnityEngine.Experimental.XR.Boundary 类型调用 TryGetGeometry 方法(指定边界类型为 TrackedArea)来获取边界多边形。 如果用户定义了一个边界(你将获得一个顶点列表),那么可以放心地向用户提供房间规模的体验,用户可以在你创建的场景中走动。
注意
当用户接近边界时,系统会自动渲染边界。 你的应用不需要使用此多边形来呈现边界本身。 不过,你可以选择使用此边界多边形进行场景对象布局,以确保用户能够以物理方式访问这些对象,而不会出现传送的情况:
var vertices = new List<Vector3>();
if (UnityEngine.Experimental.XR.Boundary.TryGetGeometry(vertices, Boundary.Type.TrackedArea))
{
// Lay out your app's content within the boundary polygon, to ensure that users can reach it without teleporting.
}
创建“世界规模”体验
命名空间:UnityEngine.XR.WSA
类型:WorldAnchor
要在 HoloLens 上获得真正的世界规模体验,让用户可以漫游 5 米以上的距离,需要使用超越房间规模体验的新技术。 你将使用的一项关键技术是创建一个空间定位点,以将一组全息影像精确锁定在物理世界中的位置(无论用户漫游了多远),然后在以后的会话中再次找到这些全息影像。
在 Unity 中,可以通过将 WorldAnchor Unity 组件添加到 GameObject 来创建空间定位点。
添加世界定位点
要添加世界定位点,请对游戏对象调用 AddComponent<WorldAnchor>(),并在现实世界中使用要定位的变换。
WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();
就这么简单! 此游戏对象现在将定位到它在物理世界中的当前位置 - 你可能会看到它的 Unity 世界坐标随着时间的推移而略有调整,以确保物理一致性。 使用持久性可在以后的应用会话中再次找到该定位点位置。
删除世界定位点
如果不再希望 GameObject 锁定到物理世界位置并且不打算在这一帧移动它,那么可以对世界定位点组件调用 Destroy。
Destroy(gameObject.GetComponent<WorldAnchor>());
如果想在这一帧中移动 GameObject,则需改为调用 DestroyImmediate。
DestroyImmediate(gameObject.GetComponent<WorldAnchor>());
移动已进行世界定位的 GameObject
GameObject 上有世界定位点时,无法移动 GameObject。 如果需要在这一帧移动 GameObject,你需要:
- 对世界定位点组件调用 DestroyImmediate
- 移动 GameObject
- 向 GameObject 添加新的世界定位点组件。
DestroyImmediate(gameObject.GetComponent<WorldAnchor>());
gameObject.transform.position = new Vector3(0, 0, 2);
WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();
处理可定位性更改
在物理世界中,可能无法在某个时间点定位 WorldAnchor。 如果发生这种情况,Unity 将不会更新已定位对象的变换。 这也可能在某个应用运行时改变。 未能处理可定位性更改会导致对象无法出现在世界上的正确物理位置。
要收到有关可定位性更改的通知,需要:
- 订阅 OnTrackingChanged 事件
- 处理事件
每当基础空间定位点在可定位状态与不可定位状态之间发生变化时,就会调用 OnTrackingChanged 事件。
anchor.OnTrackingChanged += Anchor_OnTrackingChanged;
然后处理事件:
private void Anchor_OnTrackingChanged(WorldAnchor self, bool located)
{
// This simply activates/deactivates this object and all children when tracking changes
self.gameObject.SetActiveRecursively(located);
}
有时会立即定位定位点。 在这种情况下,当 AddComponent<WorldAnchor>() 返回时,定位点的 isLocated 属性将设置为 true。 因此,不会触发 OnTrackingChanged 事件。 一个干净的模式是在附加定位点后使用初始 IsLocated 状态调用 OnTrackingChanged 处理程序。
Anchor_OnTrackingChanged(anchor, anchor.isLocated);
跨设备共享定位点
使用 Azure 空间定位点从本地 WorldAnchor 创建持久的云定位点,让应用可以跨多个 HoloLens、iOS 和 Android 设备进行定位。 通过在多个设备之间共享公用空间定位点,每个用户都可以查看相对于同一物理位置中的定位点呈现的内容。 这可实现实时共享体验。
要开始在 Unity 中构建共享体验,请参见 Azure 空间定位点 Unity 快速入门教程(只需 5 分钟)。
启动并运行 Azure 空间定位点后,可以在 Unity 中创建和定位定位点。
下一个开发检查点
如果遵循我们规划的 Unity 开发检查点旅程,则你正处于探索混合现实核心构建基块的过程中。 从这里,你可以继续了解下一部分基础知识:
或跳转到混合现实平台功能和 API:
你可以随时返回到 Unity 开发检查点。