Unity+Hololens2+WorldAnchor实现锚点锁

2023-03-05  本文已影响0人  玄策丶

本篇使用旧版Unity(2019)的WorldAnchor功能实现将物体锁定于虚拟空间的特定位置,多个物体可分别锁定锚点位置。
官方文档:https://learn.microsoft.com/zh-cn/windows/mixed-reality/develop/unity/spatial-anchors-in-unity?tabs=worldanchor

一、新建空物体挂载脚本WorldAnchorManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.WSA.Persistence;

public class WorldAnchorManager : MonoBehaviour
{
    public static WorldAnchorManager Instance;
    public bool canChangeAnchor;        //控制改变物体锚点的开关
    public WorldAnchorStore anchorStore;//保存锚点的库
    public string[] ids;

    void Awake()
    {
        Instance = this;
        //加载世界锚点
        WorldAnchorStore.GetAsync(StoreLoaded);
    }
    private void StoreLoaded(WorldAnchorStore store)
    {
        //读取所有已保存的空间锚
        anchorStore = store;
        ids = anchorStore.GetAllIds();
    }
    public void ChangeAnchor()
    {
        canChangeAnchor = !canChangeAnchor;
    }
}

二、在物体上添加组件WorldAnchor

image.png

三、在物体上添加WorldAnchorTest

将RemoveAnchor和AddAnchor方法注册到物体MRTK的操作脚本上

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.XR.WSA;

public class WorldAnchorTest : MonoBehaviour
{

    void Start()
    {
        Invoke("LoadAnchor", .1f);
    }

    void LoadAnchor()
    {
        if (WorldAnchorManager.Instance.ids.Contains(transform.name))
        {
            WorldAnchorManager.Instance.anchorStore.Load(transform.name, gameObject);
        }
    }

    /// <summary>
    /// 添加世界锚点
    /// </summary>
    public void AddAnchor()
    {
        if (!WorldAnchorManager.Instance.canChangeAnchor)
        {
            return;
        }

        Debug.Log("添加锚点");

        if (WorldAnchorManager.Instance.anchorStore == null)
        {
            return;
        }

        WorldAnchor anchor = gameObject.AddComponent<WorldAnchor>();
        if (anchor.isLocated)
        {
            WorldAnchorManager.Instance.anchorStore.Save(transform.name, anchor);
        }
        else
        {
            anchor.OnTrackingChanged += Anchor_OnTrackingChanged;
        }
    }
    void Anchor_OnTrackingChanged(WorldAnchor self, bool located)
    {
        if (located)
        {
            WorldAnchorManager.Instance.anchorStore.Save(transform.name, self);
            //取消事件监听
            self.OnTrackingChanged -= Anchor_OnTrackingChanged;
        }
    }

    /// <summary>
    /// 删除世界锚点
    /// </summary>
    public void RemoveAnchor()
    {
        if (!WorldAnchorManager.Instance.canChangeAnchor)
        {
            return;
        }

        Debug.Log("删除锚点");
        DestroyImmediate(gameObject.GetComponent<WorldAnchor>());

        if (WorldAnchorManager.Instance.anchorStore.GetAllIds().Contains(transform.name))
        {
            WorldAnchorManager.Instance.anchorStore.Delete(transform.name);
        }
    }
}
image.png
1.png
2.png

四、结语

这样就可以通过操作bool值canChangeAnchor的开关来控制是否可以移动物体添加锚点(因为有WorldAnchor存在时,物体是不可以进行操作的)。
当canChangeAnchor为flase时不可以移动操作物体(将物体锁定在场景中的某个位置)。
当canChangeAnchor为true时可以移动操作物体,并在操作结束后改变锚点的位置。

上一篇 下一篇

猜你喜欢

热点阅读