• Hololens WorldAnchor使用相关


    World Anchor空间锚提供了一种能够将物体保留在特定位置和旋转状态上的方法。这保证了全息对象的稳定性,同时提供了后续在真实世界中保持全息对象位置的能力。简单地说,你可以为全息物体来添加空间锚点,这样就能在后续步骤中将全息物体准确恢复到它原来的位置。

    Adding a World Anchor 添加空间锚


     

    命名空间: UnityEngine.VR.WSA

    类型: WorldAnchor

    Unity中添加空间锚的方式很简单,如下:

    WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();

    Removing a World Anchor 移除空间锚


     

    如果你不再想将GameObject固定在特定位置,同时在场景中也不想移动它,,那么可以调用Destroy()方法来销毁WorldAnchor组件,如下:

    Destroy(gameObject.GetComponent<WorldAnchor>());

    如果你想要立刻在场景中移动对象,那么需要调用DestroyImmediate()来销毁空间锚组件,如下:

    DestroyImmediate(gameObject.GetComponent<WorldAnchor>());

    Moving a World Anchored GameObject 移动锚定的全息对象


     

    当全息对象已附加空间锚组件后,它不能被移动。如果你需要一定全息对象的话,那么你必须这样做:

    1. 立刻销毁空间锚组件
    2. 移动全息对象
    3. 添加一个新的空间锚到全息对象上
    DestroyImmediate(gameObject.GetComponent<WorldAnchor>());
    gameObject.transform.position = new Vector3(0, 0, 2);
    WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();

    Handling Locatability Changes 处理可定位能力的变化


     

    在某个时间点,空间锚可能不能够在世界中被定位到。如果这种情况发生,Unity将不能更新锚定对象的位置。在应用运行时,这也肯能会发生变化。不能够及时处理可定位能力的变化,可能会导致对象不会出现在准确的位置上。

    为了追踪可定位能力的变化,需要采取如下做法:

    1. 订阅OnTrackingChanged事件
    2. 处理此事件

    订阅事件

    代码如下:

    anchor.OnTrackingChanged += Anchor_OnTrackingChanged;

    处理OnTrackingChanged事件

    代码如下:

    private void Anchor_OnTrackingChanged(WorldAnchor self, bool located)
    {
           // 根据定位状态简单的显示或者隐藏对象
        self.gameObject.SetActiveRecursively(located);
    }

    设定明确的初始状态

    有时空间锚能够立刻被定位到。这时候,给对象添加空间锚后,空间锚组件的isLocated属性值将会被设为true,这是OnTrackingChanged事件将不会被触发。因此,在添加空间锚组件后,推荐立刻使用初始的isLocated状态去调用OnTrackingChanged事件,如下:

    Anchor_OnTrackingChanged(anchor, anchor.isLocated)

    具体Hoolens项目中WorldAnchor 使用流程


    单例脚本中初始化WorldAnchorSotre,提取相关数据

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.Linq;
    using UnityEngine.VR.WSA.Persistence;
    using UnityEngine.UI;
    using UnityEngine.VR.WSA;

    public class ModelManager : Singleton<ModelManager> {

      public WorldAnchorStore anchorStore;

      IEnumerator Start(){

        WorldAnchorStore.GetAsync(Ready);
        yield return new WaitForEndOfFrame();
      }

      private void Ready(WorldAnchorStore store)
      {
        anchorStore = store;
        string[] ids = anchorStore.GetAllIds();
        ids.ToList().ForEach((s) =>
        {

          //根据数据加载相关模型
          GameObject model = LoadModel(s);

          //此处Load 包括Transform 位置与旋转信息
          WorldAnchor wa = anchorStore.Load(s, model);
        });
       }

      public GameObject LoadModel(string name) {
        GameObject m_Model = Instantiate(Resources.Load(m_ModelPath + name)) as GameObject;
        m_Model.transform.SetParent(ModelManager.Instance.transform);
        m_Model.name = name;
        return m_Model;
      }

    }



    增加与删除空间锚点(具体到某个物体)

    需定位的物体(可移动)

    using UnityEngine;
    using System;
    using UnityEngine.VR.WSA.Persistence;
    using UnityEngine.VR.WSA;
    using System.Collections;

    public class Model:Monobehaviour{

      string ObjectAnchorStoreName;

      public WorldAnchorStore anchorStore;

      void Start(){

        anchorStore  = ModelManager.Instance.anchorStore;

        ObjectAnchorStoreName = gameobject.name;

      }

      public void AnchorFunc(){

        if (anchorStore == null){

          return;
        }

        //此处不包含拖拽移动逻辑  

        if (!isDragging){     

            WorldAnchor attachingAnchor = gameObject.AddComponent<WorldAnchor>();

            if (attachingAnchor.isLocated)
            {
              bool saved = anchorStore.Save(ObjectAnchorStoreName, attachingAnchor);
            }
            else
            {
              //有时空间锚能够立刻被定位到。这时候,给对象添加空间锚后,空间锚组件的isLocated属性
              //值将会被设为true,这时OnTrackingChanged事件将不会被触发。因此,在添加空间锚组件
              //后,推荐立刻使用初始的isLocated状态去调用OnTrackingChanged事件
              attachingAnchor.OnTrackingChanged += AttachingAnchor_OnTrackingChanged;
            }
        }
        else{
          //当全息对象已附加空间锚组件后,它不能被移动。如果你需要移动全息对象的话,那么你必须这样做:
          //1.立刻销毁空间锚组件
          //2.移动全息对象
          //3.添加一个新的空间锚到全息对象上
          WorldAnchor anchor = gameObject.GetComponent<WorldAnchor>();
          if (anchor != null)
          {
            DestroyImmediate(anchor);
          }
          DeleteAnchor(ObjectAnchorStoreName);
        }
      }

      //根据锚点名字删除空间锚点

      public void DeleteAnchor(string name) {
        string[] ids = anchorStore.GetAllIds();
        for (int index = 0; index < ids.Length; index++)
        {
          if (ids[index] == name)
          {
            bool deleted = anchorStore.Delete(ids[index]);
            break;
          }
        }
      }

      private void AttachingAnchor_OnTrackingChanged(WorldAnchor self, bool located)
      {
        if (located)
        {
          bool saved = anchorStore.Save(ObjectAnchorStoreName, self);
          self.OnTrackingChanged -= AttachingAnchor_OnTrackingChanged;
        }
      }

    }

     

  • 相关阅读:
    3-12 初识JWT
    3-11 用户登录信息验证实现
    3-10 公共模块统一测试
    3-9 公共业务异常统一处理
    3-8 公共返回对象封装
    3-7 公共请求对象封装及优雅验证数据实现
    3-6 MD5介绍及用户添加功能实现
    3-5 用户模块数据层构建
    3-4 用户模块构建
    3-3 公共工具模块构建
  • 原文地址:https://www.cnblogs.com/monkeyst/p/7210745.html
Copyright © 2020-2023  润新知