8 using System.Collections.Generic;
9 #if UNITY_2017_2_OR_NEWER 38 [Tooltip(
"Enables detailed logs in console window. If the Sharing Service is used, it will inherit the log settings.")]
44 [Tooltip(
"Enables anchors to be stored from subsequent game sessions.")]
48 protected struct AnchorAttachmentInfo
57 public GameObject AnchoredGameObject {
get;
set; }
58 public string AnchorName {
get;
set; }
59 public AnchorOperation Operation {
get;
set; }
65 protected enum AnchorOperation
80 protected Queue<AnchorAttachmentInfo> LocalAnchorOperations =
new Queue<AnchorAttachmentInfo>();
86 public WorldAnchorStore AnchorStore {
get;
protected set; }
91 protected Dictionary<string, GameObject> AnchorGameObjectReferenceList =
new Dictionary<string, GameObject>(0);
95 protected override void Awake()
101 protected virtual void Start()
103 WorldAnchorStore.GetAsync(AnchorStoreReady);
106 protected virtual void Update()
108 if (AnchorStore == null) {
return; }
110 if (LocalAnchorOperations.Count > 0)
112 DoAnchorOperation(LocalAnchorOperations.Dequeue());
116 #endregion // Unity Methods 118 #region Event Callbacks 124 protected virtual void AnchorStoreReady(WorldAnchorStore anchorStore)
126 AnchorStore = anchorStore;
128 if (!PersistentAnchors)
141 private void Anchor_OnTrackingChanged(WorldAnchor anchor,
bool located)
143 if (located && SaveAnchor(anchor))
145 if (ShowDetailedLogs)
147 Debug.LogFormat(
"[WorldAnchorManager] Successfully updated cached anchor \"{0}\".", anchor.name);
150 if (AnchorDebugText != null)
152 AnchorDebugText.text +=
string.Format(
"\nSuccessfully updated cached anchor \"{0}\".", anchor.name);
157 if (ShowDetailedLogs)
159 Debug.LogFormat(
"[WorldAnchorManager] Failed to locate cached anchor \"{0}\", attempting to acquire anchor again.", anchor.name);
162 if (AnchorDebugText != null)
164 AnchorDebugText.text +=
string.Format(
"\nFailed to locate cached anchor \"{0}\", attempting to acquire anchor again.", anchor.name);
167 GameObject anchoredObject;
168 AnchorGameObjectReferenceList.TryGetValue(anchor.name, out anchoredObject);
169 AnchorGameObjectReferenceList.Remove(anchor.name);
170 AttachAnchor(anchoredObject, anchor.name);
173 anchor.OnTrackingChanged -= Anchor_OnTrackingChanged;
176 #endregion // Event Callbacks 178 public static string GenerateAnchorName(GameObject gameObjectToAnchor,
string proposedAnchorname = null)
187 return string.IsNullOrEmpty(proposedAnchorname) ? gameObjectToAnchor.name : proposedAnchorname;
199 public string AttachAnchor(GameObject gameObjectToAnchor,
string anchorName = null)
201 #if !UNITY_WSA || UNITY_EDITOR 202 Debug.LogWarning(
"World Anchor Manager does not work for this build. AttachAnchor will not be called.");
205 if (gameObjectToAnchor == null)
207 Debug.LogError(
"[WorldAnchorManager] Must pass in a valid gameObject");
212 if (AnchorStore == null)
214 Debug.LogWarning(
"[WorldAnchorManager] AttachAnchor called before anchor store is ready.");
217 anchorName = GenerateAnchorName(gameObjectToAnchor, anchorName);
219 LocalAnchorOperations.Enqueue(
220 new AnchorAttachmentInfo
222 AnchoredGameObject = gameObjectToAnchor,
223 AnchorName = anchorName,
224 Operation = AnchorOperation.Save
238 if (gameObjectToUnanchor == null)
240 Debug.LogError(
"[WorldAnchorManager] Invalid GameObject! Try removing anchor by name.");
241 if (AnchorDebugText != null)
243 AnchorDebugText.text +=
"\nInvalid GameObject! Try removing anchor by name.";
248 RemoveAnchor(
string.Empty, gameObjectToUnanchor);
258 if (
string.IsNullOrEmpty(anchorName))
260 Debug.LogErrorFormat(
"[WorldAnchorManager] Invalid anchor \"{0}\"! Try removing anchor by GameObject.", anchorName);
261 if (AnchorDebugText != null)
263 AnchorDebugText.text +=
string.Format(
"\nInvalid anchor \"{0}\"! Try removing anchor by GameObject.", anchorName);
268 RemoveAnchor(anchorName, null);
277 private void RemoveAnchor(
string anchorName, GameObject gameObjectToUnanchor)
279 if (
string.IsNullOrEmpty(anchorName) && gameObjectToUnanchor == null)
281 Debug.LogWarning(
"Invalid Remove Anchor Request!");
285 #if !UNITY_WSA || UNITY_EDITOR 286 Debug.LogWarning(
"World Anchor Manager does not work for this build. RemoveAnchor will not be called.");
289 if (AnchorStore == null)
291 Debug.LogWarning(
"[WorldAnchorManager] RemoveAnchor called before anchor store is ready.");
294 LocalAnchorOperations.Enqueue(
295 new AnchorAttachmentInfo
297 AnchoredGameObject = gameObjectToUnanchor,
298 AnchorName = anchorName,
299 Operation = AnchorOperation.Delete
309 #if !UNITY_WSA || UNITY_EDITOR 310 Debug.LogWarning(
"World Anchor Manager does not work for this build. RemoveAnchor will not be called.");
312 SpatialMappingManager spatialMappingManager = SpatialMappingManager.Instance;
315 if (AnchorStore == null)
317 Debug.LogWarning(
"[WorldAnchorManager] RemoveAllAnchors called before anchor store is ready.");
320 var anchors = FindObjectsOfType<WorldAnchor>();
322 if (anchors == null) {
return; }
324 for (var i = 0; i < anchors.Length; i++)
327 if (spatialMappingManager != null && anchors[i].gameObject.transform.parent.gameObject == spatialMappingManager.gameObject)
332 if (!AnchorGameObjectReferenceList.ContainsKey(anchors[i].name))
334 Debug.LogWarning(
"[WorldAnchorManager] Removing an anchor that was created outside of the WorldAnchorManager. Please use the WorldAnchorManager to create or delete anchors.");
335 if (AnchorDebugText != null)
337 AnchorDebugText.text +=
string.Format(
"\nRemoving an anchor that was created outside of the WorldAnchorManager. Please use the WorldAnchorManager to create or delete anchors.");
341 LocalAnchorOperations.Enqueue(
new AnchorAttachmentInfo
343 AnchorName = anchors[i].name,
344 AnchoredGameObject = anchors[i].gameObject,
345 Operation = AnchorOperation.Delete
352 protected void DoAnchorOperation(AnchorAttachmentInfo anchorAttachmentInfo)
358 string anchorId = anchorAttachmentInfo.AnchorName;
359 GameObject anchoredGameObject = anchorAttachmentInfo.AnchoredGameObject;
361 switch (anchorAttachmentInfo.Operation)
363 case AnchorOperation.Save:
364 if (anchoredGameObject == null)
366 Debug.LogError(
"[WorldAnchorManager] The GameObject referenced must have been destroyed before we got a chance to anchor it.");
367 if (AnchorDebugText != null)
369 AnchorDebugText.text +=
"\nThe GameObject referenced must have been destroyed before we got a chance to anchor it.";
374 if (
string.IsNullOrEmpty(anchorId))
376 anchorId = anchoredGameObject.name;
380 WorldAnchor savedAnchor = AnchorStore.Load(anchorId, anchoredGameObject);
382 if (savedAnchor == null)
385 if (ImportAnchor(anchorId, anchoredGameObject) ==
false)
387 if (ShowDetailedLogs)
389 Debug.LogFormat(
"[WorldAnchorManager] Anchor could not be loaded for \"{0}\". Creating a new anchor.", anchoredGameObject.name);
392 if (AnchorDebugText != null)
394 AnchorDebugText.text +=
string.Format(
"\nAnchor could not be loaded for \"{0}\". Creating a new anchor.", anchoredGameObject.name);
398 CreateAnchor(anchoredGameObject, anchorId);
403 savedAnchor.name = anchorId;
404 if (ShowDetailedLogs)
406 Debug.LogFormat(
"[WorldAnchorManager] Anchor loaded from anchor store and updated for \"{0}\".", anchoredGameObject.name);
409 if (AnchorDebugText != null)
411 AnchorDebugText.text +=
string.Format(
"\nAnchor loaded from anchor store and updated for \"{0}\".", anchoredGameObject.name);
415 AnchorGameObjectReferenceList.Add(anchorId, anchoredGameObject);
417 case AnchorOperation.Delete:
418 if (AnchorStore == null)
420 Debug.LogError(
"[WorldAnchorManager] Remove anchor called before anchor store is ready.");
425 if (!
string.IsNullOrEmpty(anchorId) && anchoredGameObject == null)
427 AnchorGameObjectReferenceList.TryGetValue(anchorId, out anchoredGameObject);
430 if (anchoredGameObject != null)
432 var anchor = anchoredGameObject.GetComponent<WorldAnchor>();
436 anchorId = anchor.name;
437 DestroyImmediate(anchor);
441 Debug.LogErrorFormat(
"[WorldAnchorManager] Unable remove WorldAnchor from {0}!", anchoredGameObject.name);
442 if (AnchorDebugText != null)
444 AnchorDebugText.text +=
string.Format(
"\nUnable remove WorldAnchor from {0}!", anchoredGameObject.name);
450 Debug.LogError(
"[WorldAnchorManager] Unable find a GameObject to remove an anchor from!");
451 if (AnchorDebugText != null)
453 AnchorDebugText.text +=
"\nUnable find a GameObject to remove an anchor from!";
457 if (!
string.IsNullOrEmpty(anchorId))
459 AnchorGameObjectReferenceList.Remove(anchorId);
460 DeleteAnchor(anchorId);
464 Debug.LogError(
"[WorldAnchorManager] Unable find an anchor to delete!");
465 if (AnchorDebugText != null)
467 AnchorDebugText.text +=
"\nUnable find an anchor to delete!";
473 throw new ArgumentOutOfRangeException();
482 private void CreateAnchor(GameObject gameObjectToAnchor,
string anchorName)
484 var anchor = gameObjectToAnchor.EnsureComponent<WorldAnchor>();
485 anchor.name = anchorName;
488 if (anchor.isLocated)
495 anchor.OnTrackingChanged += Anchor_OnTrackingChanged;
503 private bool SaveAnchor(WorldAnchor anchor)
506 if (AnchorStore.Save(anchor.name, anchor))
508 if (ShowDetailedLogs)
510 Debug.LogFormat(
"[WorldAnchorManager] Successfully saved anchor \"{0}\".", anchor.name);
513 if (AnchorDebugText != null)
515 AnchorDebugText.text +=
string.Format(
"\nSuccessfully saved anchor \"{0}\".", anchor.name);
518 ExportAnchor(anchor);
523 Debug.LogErrorFormat(
"[WorldAnchorManager] Failed to save anchor \"{0}\"!", anchor.name);
525 if (AnchorDebugText != null)
527 AnchorDebugText.text +=
string.Format(
"\nFailed to save anchor \"{0}\"!", anchor.name);
536 private void DeleteAnchor(
string anchorId)
538 if (AnchorStore.Delete(anchorId))
540 Debug.LogFormat(
"[WorldAnchorManager] Anchor {0} deleted successfully.", anchorId);
541 if (AnchorDebugText != null)
543 AnchorDebugText.text +=
string.Format(
"\nAnchor {0} deleted successfully.", anchorId);
548 if (
string.IsNullOrEmpty(anchorId))
553 Debug.LogErrorFormat(
"[WorldAnchorManager] Failed to delete \"{0}\".", anchorId);
554 if (AnchorDebugText != null)
556 AnchorDebugText.text +=
string.Format(
"\nFailed to delete \"{0}\".", anchorId);
567 protected virtual bool ImportAnchor(
string anchorId, GameObject objectToAnchor)
577 protected virtual void ExportAnchor(WorldAnchor anchor) { }