本篇使用舊版Unity(2019)的WorldAnchor功能實現(xiàn)將物體鎖定于虛擬空間的特定位置,多個物體可分別鎖定錨點位置。
官方文檔:https://learn.microsoft.com/zh-cn/windows/mixed-reality/develop/unity/spatial-anchors-in-unity?tabs=worldanchor
一、新建空物體掛載腳本W(wǎng)orldAnchorManager
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; //控制改變物體錨點的開關(guān)
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);
//取消事件監(jiān)聽
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
四、結(jié)語
這樣就可以通過操作bool值canChangeAnchor的開關(guān)來控制是否可以移動物體添加錨點(因為有WorldAnchor存在時,物體是不可以進(jìn)行操作的)。
當(dāng)canChangeAnchor為flase時不可以移動操作物體(將物體鎖定在場景中的某個位置)。
當(dāng)canChangeAnchor為true時可以移動操作物體,并在操作結(jié)束后改變錨點的位置。