Closed ian-phoria closed 4 years ago
I can confirm the problem.
Tested with ASA SDK v2.2.1 and v2.4.0 Unity 2013.3.15f1 iPhone 10
Additional information:
Create a new anchor. -->
Scenario 1: Starting the application with LocateStrategy.AnyStrategy, i am able to locate every anchor and the new created anchor. Quit Application.
Scenario 2: Starting the application with LocateStrategy.VisualInformation, i am only able to find the new anchor for a few minutes. Quit Application.
Scenario 3: Starting the application with LocateStrategy.AnyStrategy, i am able to locate every anchor and the new created anchor. Changing to LocateStrategy.VisualInformation without quitting the application, i am only able to find the new created anchor. Changing back to LocateStrategy.AnyStrategy or LocateStrategy.Relationship i am only able to find the new created anchor and all other anchors that were locatable at appstart can no longer be found. Quit Application.
We believe we understand this cause of this behavior regression. We are validating a server-side fix and will post more details as we have them. ETA for an update is 48 hours from now.
As a mitigation, use LocateStrategy.AnyStrategy
for now.
We have applied a server-side change that we believe will fix this problem.
If you still encounter it, can additional details here:
(None of these values are sensitive. You can post them here in the clear.)
Thanks for the feedback. It's working again as expected. All anchors are located as before. Changing the LocateStrategy without leaving the app works again.
But, there is still one bug: My app only queries certain anchors by location. I created an anchor at my location yesterday, before the patch. This anchor was not deleted from the cloud. But I don't search for this anchor ID at my location.
When the app is started with LocateStrategy.VisualInformation, everything works as usual and all anchors are found at the corresponding locations that were searched for. If i switch to LocateStrategy.AnyStrategy, the anchor created yesterday will be found but not at the position of yesterday but always directly at the location of the phone. As soon as the anchor from yesterday is found, for all other anchors the AnchorFoundEvent is triggered but the AnchorLocateStatus is not LocateAnchorStatus.Located.
Can you open a different issue for what you're seeing? I don't think it's related to this bug. There bug in the service prevented it from ever returning a "located" result for the affected anchors when LocateStrategy.VisualInformation
was used. Since you are getting a LocateAnchorStatus.Located
callback using LocateStrategy.VisualInformation
, I think something else is happening.
Please include your ASA account id, the anchor ids for the anchors, which anchors are which in your scenario, and any RespCV values you have from the ASA SDK log.
I just customized Nearby Anchor Demo to place the Anchors in one scene and locating the anchor in Second Scene ( Android) The anchor ids are passed to the BasicDemoscript from nearbyanchor saerching method. But the 3d object is not spawning in anchor position. I am using latest version of SDK
Please Help me to sort out this The code is attached below
Saving anchors
`// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using UnityEngine; using UnityEngine.UI;
namespace Microsoft.Azure.SpatialAnchors.Unity.Examples { public class AzureSpatialAnchorsNearbyDemoScript : DemoScriptBase { internal enum AppState { Placing = 0, Saving, ReadyToSearch, Searching, ReadyToNeighborQuery, Neighboring, Deleting, Done, ModeCount }
private readonly Color[] colors =
{
Color.white,
Color.magenta,
Color.magenta,
Color.cyan,
Color.magenta,
Color.green,
Color.grey,
Color.grey
};
private readonly Vector3[] scaleMods =
{
new Vector3(0,0,0),
new Vector3(0,0,0),
new Vector3(0,0,0),
new Vector3(0,0,.1f),
new Vector3(0,0,0),
new Vector3(0,.1f,0),
new Vector3(0,0,0),
new Vector3(0,0,0)
};
private readonly int numToMake = 3;
public Text DebugText;
private AppState _currentAppState = AppState.Placing;
AppState currentAppState
{
get
{
return _currentAppState;
}
set
{
if (_currentAppState != value)
{
Debug.LogFormat("State from {0} to {1}", _currentAppState, value);
_currentAppState = value;
}
}
}
readonly List<string> anchorIds = new List<string>();
readonly Dictionary<AppState, Dictionary<string, GameObject>> spawnedObjectsPerAppState = new Dictionary<AppState, Dictionary<string, GameObject>>();
Dictionary<string, GameObject> spawnedObjectsInCurrentAppState
{
get
{
if (spawnedObjectsPerAppState.ContainsKey(_currentAppState) == false)
{
spawnedObjectsPerAppState.Add(_currentAppState, new Dictionary<string, GameObject>());
}
return spawnedObjectsPerAppState[_currentAppState];
}
}
/// <summary>
/// Start is called on the frame when a script is enabled just before any
/// of the Update methods are called the first time.
/// </summary>
public override void Start()
{
Debug.Log(">>Azure Spatial Anchors Demo Script Start");
base.Start();
if (!SanityCheckAccessConfiguration())
{
return;
}
feedbackBox.text = "Find nearby demo. First, we need to place a few anchors. Tap somewhere to place the first one";
Debug.Log("Azure Spatial Anchors Demo script started");
}
/// <summary>
/// Update is called every frame, if the MonoBehaviour is enabled.
/// </summary>
public override void Update()
{
base.Update();
HandleCurrentAppState();
}
private void HandleCurrentAppState()
{
int timeLeft = (int)(dueDate - DateTime.Now).TotalSeconds;
switch (currentAppState)
{
case AppState.ReadyToSearch:
feedbackBox.text = "Next: Tap to start looking for just the first anchor we placed.";
break;
case AppState.Searching:
feedbackBox.text = $"Looking for the first anchor you made. Give up in {timeLeft}";
if (timeLeft < 0)
{
Debug.Log("Out of time");
// Restart the demo..
feedbackBox.text = "Failed to find the first anchor. Try again.";
currentAppState = AppState.Done;
}
break;
case AppState.ReadyToNeighborQuery:
feedbackBox.text = "Next: Tap to start looking for anchors nearby the first anchor we placed.";
break;
case AppState.Neighboring:
// We should find all anchors except for the anchor we are using as the source anchor.
feedbackBox.text = $"Looking for anchors nearby the first anchor. {locatedCount}/{numToMake - 1} {timeLeft}";
if (timeLeft < 0)
{
feedbackBox.text = "Failed to find all the neighbors. Tap to delete anchors.";
currentAppState = AppState.Deleting;
}
if (locatedCount == numToMake - 1)
{
feedbackBox.text = "Found them all! Tap to delete anchors.";
currentAppState = AppState.Deleting;
}
break;
}
}
protected override bool IsPlacingObject()
{
return currentAppState == AppState.Placing;
}
protected override Color GetStepColor()
{
return colors[(int)currentAppState];
}
private int locatedCount = 0;
protected override void OnCloudAnchorLocated(AnchorLocatedEventArgs args)
{
base.OnCloudAnchorLocated(args);
if (args.Status == LocateAnchorStatus.Located)
{
UnityDispatcher.InvokeOnAppThread(() =>
{
locatedCount++;
currentCloudAnchor = args.Anchor;
Pose anchorPose = currentCloudAnchor.GetPose();
SpawnOrMoveCurrentAnchoredObject(anchorPose.position, anchorPose.rotation);
spawnedObject.transform.localScale += scaleMods[(int)currentAppState];
spawnedObject = null;
if (currentAppState == AppState.Searching)
{
currentAppState = AppState.ReadyToNeighborQuery;
}
});
}
}
private DateTime dueDate = DateTime.Now;
private readonly List<GameObject> allSpawnedObjects = new List<GameObject>();
private readonly List<Material> allSpawnedMaterials = new List<Material>();
protected override void SpawnOrMoveCurrentAnchoredObject(Vector3 worldPos, Quaternion worldRot)
{
if (currentCloudAnchor != null && spawnedObjectsInCurrentAppState.ContainsKey(currentCloudAnchor.Identifier))
{
spawnedObject = spawnedObjectsInCurrentAppState[currentCloudAnchor.Identifier];
}
bool spawnedNewObject = spawnedObject == null;
base.SpawnOrMoveCurrentAnchoredObject(worldPos, worldRot);
if (spawnedNewObject)
{
allSpawnedObjects.Add(spawnedObject);
allSpawnedMaterials.Add(spawnedObjectMat);
if (currentCloudAnchor != null && spawnedObjectsInCurrentAppState.ContainsKey(currentCloudAnchor.Identifier) == false)
{
spawnedObjectsInCurrentAppState.Add(currentCloudAnchor.Identifier, spawnedObject);
}
}
#if WINDOWS_UWP || UNITY_WSA
if (currentCloudAnchor != null
&& spawnedObjectsInCurrentAppState.ContainsKey(currentCloudAnchor.Identifier) == false)
{
spawnedObjectsInCurrentAppState.Add(currentCloudAnchor.Identifier, spawnedObject);
}
#endif
}
public async override Task AdvanceDemoAsync()
{
switch (currentAppState)
{
case AppState.Placing:
if (spawnedObject != null)
{
currentAppState = AppState.Saving;
if (!CloudManager.IsSessionStarted)
{
await CloudManager.StartSessionAsync();
}
await SaveCurrentObjectAnchorToCloudAsync();
}
break;
case AppState.ReadyToSearch:
await DoSearchingPassAsync();
break;
case AppState.ReadyToNeighborQuery:
DoNeighboringPassAsync();
break;
case AppState.Deleting:
foreach (var anchorIdentifier in anchorIds)
{
CloudSpatialAnchor anchorToBeDeleted = await CloudManager.Session.GetAnchorPropertiesAsync(anchorIdentifier);
if (anchorToBeDeleted == null)
{
Debug.LogError("Failed to get properties for anchor: " + anchorIdentifier);
continue;
}
await CloudManager.DeleteAnchorAsync(anchorToBeDeleted);
}
CleanupObjectsBetweenPasses();
currentAppState = AppState.Done;
feedbackBox.text = $"Finished deleting anchors. Tap to restart.";
break;
case AppState.Done:
await CloudManager.ResetSessionAsync();
//Added -- This script for later use of saved Data
currentAppState = AppState.Placing;
feedbackBox.text = $"Place an object. {allSpawnedObjects.Count}/{numToMake} ";
break;
}
}
protected override async Task OnSaveCloudAnchorSuccessfulAsync()
{
await base.OnSaveCloudAnchorSuccessfulAsync();
Debug.Log("Anchor created, yay!");
anchorIds.Add(currentCloudAnchor.Identifier);
spawnedObject = null;
currentCloudAnchor = null;
if (allSpawnedObjects.Count < numToMake)
{
feedbackBox.text = $"Saved...Make another {allSpawnedObjects.Count}/{numToMake} ";
currentAppState = AppState.Placing;
}
else
{
feedbackBox.text = "Saved... ready to start finding them.";
currentAppState = AppState.Done;
//Saving Anchors for Later use
string anchorIdsJson = JsonUtility.ToJson(anchorIds);
PlayerPrefs.SetString("AnchorIds", anchorIdsJson);
PlayerPrefs.Save();
DebugText.text = anchorIds[2];
Debug.Log(anchorIds[0]);
Debug.Log(anchorIds[1]);
Debug.Log(anchorIds[2]);
}
}
protected override void OnSaveCloudAnchorFailed(Exception exception)
{
base.OnSaveCloudAnchorFailed(exception);
}
private async Task DoSearchingPassAsync()
{
await CloudManager.ResetSessionAsync();
SetGraphEnabled(true); // set LocateStrategy to VisualInformation
IEnumerable<string> anchorsToFind = new[] { anchorIds[0] };
SetAnchorIdsToLocate(anchorsToFind);
locatedCount = 0;
dueDate = DateTime.Now.AddSeconds(30);
currentWatcher = CreateWatcher();
currentAppState = AppState.Searching;
}
private void DoNeighboringPassAsync()
{
SetGraphEnabled(true, true); // set LocateStrategy to Relationship
ResetAnchorIdsToLocate();
SetNearbyAnchor(currentCloudAnchor, 10, numToMake);
locatedCount = 0;
dueDate = DateTime.Now.AddSeconds(30);
currentWatcher = CreateWatcher();
currentAppState = AppState.Neighboring;
}
private void CleanupObjectsBetweenPasses()
{
foreach (GameObject go in allSpawnedObjects)
{
Destroy(go);
}
allSpawnedObjects.Clear();
foreach (Material m in allSpawnedMaterials)
{
Destroy(m);
}
allSpawnedMaterials.Clear();
currentCloudAnchor = null;
spawnedObject = null;
spawnedObjectMat = null;
spawnedObjectsPerAppState.Clear();
anchorIds.Clear();
}
public void SavePref()
{
int i = 0;
foreach (string str in anchorIds)
{
PlayerPrefs.SetString("azureinfo" + i, anchorIds[i]);
i++;
}
PlayerPrefs.SetInt("KeyCount", i);
}
}
} ` Reloading
`// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using UnityEngine;
namespace Microsoft.Azure.SpatialAnchors.Unity.Examples { public class AzureSpatialAnchorsNearbyDemoScript1:DemoScriptBase { internal enum AppState { //Placing, //Saving, ReadyToSearch=0, Searching, ReadyToNeighborQuery, Neighboring, Deleting, Done, ModeCount }
private readonly Color[] colors =
{
Color.white,
Color.magenta,
Color.magenta,
Color.cyan,
Color.magenta,
Color.green,
Color.grey,
Color.grey
};
private readonly Vector3[] scaleMods =
{
new Vector3(0,0,0),
new Vector3(0,0,0),
new Vector3(0,0,0),
new Vector3(0,0,.1f),
new Vector3(0,0,0),
new Vector3(0,.1f,0),
new Vector3(0,0,0),
new Vector3(0,0,0)
};
private readonly int numToMake = 3;
private AppState _currentAppState = AppState.ReadyToSearch;
AppState currentAppState
{
get
{
return _currentAppState;
}
set
{
if (_currentAppState != value)
{
Debug.LogFormat("State from {0} to {1}", _currentAppState, value);
_currentAppState = value;
}
}
}
readonly List<string> anchorIds = new List<string>();
readonly Dictionary<AppState, Dictionary<string, GameObject>> spawnedObjectsPerAppState = new Dictionary<AppState, Dictionary<string, GameObject>>();
Dictionary<string, GameObject> spawnedObjectsInCurrentAppState
{
get
{
if (spawnedObjectsPerAppState.ContainsKey(_currentAppState) == false)
{
spawnedObjectsPerAppState.Add(_currentAppState, new Dictionary<string, GameObject>());
}
return spawnedObjectsPerAppState[_currentAppState];
}
}
/// <summary>
/// Start is called on the frame when a script is enabled just before any
/// of the Update methods are called the first time.
/// </summary>
public override void Start()
{
Debug.Log(">>Azure Spatial Anchors Demo Script Start");
base.Start();
if (!SanityCheckAccessConfiguration())
{
return;
}
//feedbackBox.text = "Find nearby demo. First, we need to place a few anchors. Tap somewhere to place the first one";
Debug.Log("Azure Spatial Anchors Demo script started");
int keyCount = PlayerPrefs.GetInt("KeyCount");
Debug.Log(keyCount);
for (int i = 0; i < keyCount; i++)
{
string data = PlayerPrefs.GetString("azureinfo" + i);
anchorIds.Add(data);
//Debug.Log(data);
}
//Checking anchor values
foreach(string str in anchorIds)
{
Debug.Log(str);
}
}
/// <summary>
/// Update is called every frame, if the MonoBehaviour is enabled.
/// </summary>
public override void Update()
{
base.Update();
HandleCurrentAppState();
}
private void HandleCurrentAppState()
{
int timeLeft = (int)(dueDate - DateTime.Now).TotalSeconds;
switch (currentAppState)
{
case AppState.ReadyToSearch:
feedbackBox.text = "Next: Tap to start looking for just the first anchor we placed.";
break;
case AppState.Searching:
feedbackBox.text = $"Looking for the first anchor you made. Give up in {timeLeft}";
if (timeLeft < 0)
{
Debug.Log("Out of time");
// Restart the demo..
feedbackBox.text = "Failed to find the first anchor. Try again.";
currentAppState = AppState.Done;
}
break;
case AppState.ReadyToNeighborQuery:
feedbackBox.text = "Next: Tap to start looking for anchors nearby the first anchor we placed.";
break;
case AppState.Neighboring:
// We should find all anchors except for the anchor we are using as the source anchor.
feedbackBox.text = $"Looking for anchors nearby the first anchor. {locatedCount}/{numToMake - 1} {timeLeft}";
if (timeLeft < 0)
{
feedbackBox.text = "Failed to find all the neighbors. Tap to delete anchors.";
currentAppState = AppState.Deleting;
}
if (locatedCount == numToMake - 1)
{
feedbackBox.text = "Found them all! Tap to delete anchors.";
currentAppState = AppState.Deleting;
}
break;
}
}
//protected override bool IsPlacingObject()
//{
// //return currentAppState == AppState.Placing;
//}
protected override Color GetStepColor()
{
return colors[(int)currentAppState];
}
private int locatedCount = 0;
protected override void OnCloudAnchorLocated(AnchorLocatedEventArgs args)
{
base.OnCloudAnchorLocated(args);
if (args.Status == LocateAnchorStatus.Located)
{
UnityDispatcher.InvokeOnAppThread(() =>
{
locatedCount++;
currentCloudAnchor = args.Anchor;
Debug.Log("CurrentCloudAnchor" + currentCloudAnchor);
Pose anchorPose = currentCloudAnchor.GetPose();
SpawnOrMoveCurrentAnchoredObject(anchorPose.position, anchorPose.rotation);
spawnedObject.transform.localScale += scaleMods[(int)currentAppState];
spawnedObject = null;
if (currentAppState == AppState.Searching)
{
currentAppState = AppState.ReadyToNeighborQuery;
}
});
}
}
private DateTime dueDate = DateTime.Now;
private readonly List<GameObject> allSpawnedObjects = new List<GameObject>();
private readonly List<Material> allSpawnedMaterials = new List<Material>();
protected override void SpawnOrMoveCurrentAnchoredObject(Vector3 worldPos, Quaternion worldRot)
{
if (currentCloudAnchor != null && spawnedObjectsInCurrentAppState.ContainsKey(currentCloudAnchor.Identifier))
{
spawnedObject = spawnedObjectsInCurrentAppState[currentCloudAnchor.Identifier];
}
bool spawnedNewObject = spawnedObject == null;
base.SpawnOrMoveCurrentAnchoredObject(worldPos, worldRot);
if (spawnedNewObject)
{
allSpawnedObjects.Add(spawnedObject);
allSpawnedMaterials.Add(spawnedObjectMat);
if (currentCloudAnchor != null && spawnedObjectsInCurrentAppState.ContainsKey(currentCloudAnchor.Identifier) == false)
{
spawnedObjectsInCurrentAppState.Add(currentCloudAnchor.Identifier, spawnedObject);
}
}
#if WINDOWS_UWP || UNITY_WSA
if (currentCloudAnchor != null
&& spawnedObjectsInCurrentAppState.ContainsKey(currentCloudAnchor.Identifier) == false)
{
spawnedObjectsInCurrentAppState.Add(currentCloudAnchor.Identifier, spawnedObject);
}
#endif
}
public async override Task AdvanceDemoAsync()
{
switch (currentAppState)
{
//case AppState.Placing:
// if (spawnedObject != null)
// {
// currentAppState = AppState.Saving;
// if (!CloudManager.IsSessionStarted)
// {
// await CloudManager.StartSessionAsync();
// }
// await SaveCurrentObjectAnchorToCloudAsync();
// }
// break;
case AppState.ReadyToSearch:
await DoSearchingPassAsync();
break;
case AppState.ReadyToNeighborQuery:
DoNeighboringPassAsync();
break;
case AppState.Deleting:
foreach (var anchorIdentifier in anchorIds)
{
CloudSpatialAnchor anchorToBeDeleted = await CloudManager.Session.GetAnchorPropertiesAsync(anchorIdentifier);
if (anchorToBeDeleted == null)
{
Debug.LogError("Failed to get properties for anchor: " + anchorIdentifier);
continue;
}
await CloudManager.DeleteAnchorAsync(anchorToBeDeleted);
}
CleanupObjectsBetweenPasses();
currentAppState = AppState.Done;
feedbackBox.text = $"Finished deleting anchors. Tap to restart.";
break;
case AppState.Done:
await CloudManager.ResetSessionAsync();
//currentAppState = AppState.Placing;
feedbackBox.text = $"Place an object. {allSpawnedObjects.Count}/{numToMake} ";
break;
}
}
protected override async Task OnSaveCloudAnchorSuccessfulAsync()
{
await base.OnSaveCloudAnchorSuccessfulAsync();
Debug.Log("Anchor created, yay!");
anchorIds.Add(currentCloudAnchor.Identifier);
spawnedObject = null;
currentCloudAnchor = null;
if (allSpawnedObjects.Count < numToMake)
{
feedbackBox.text = $"Saved...Make another {allSpawnedObjects.Count}/{numToMake} ";
//currentAppState = AppState.Placing;
}
else
{
feedbackBox.text = "Saved... ready to start finding them.";
currentAppState = AppState.ReadyToSearch;
}
}
protected override void OnSaveCloudAnchorFailed(Exception exception)
{
base.OnSaveCloudAnchorFailed(exception);
}
private async Task DoSearchingPassAsync()
{
await CloudManager.ResetSessionAsync();
SetGraphEnabled(true); // set LocateStrategy to VisualInformation
IEnumerable<string> anchorsToFind = new[] { anchorIds[0] };
SetAnchorIdsToLocate(anchorsToFind);
locatedCount = 0;
dueDate = DateTime.Now.AddSeconds(30);
currentWatcher = CreateWatcher();
currentAppState = AppState.Searching;
Debug.Log("Anchors to find: " + string.Join(", ", anchorIdsToLocate));
}
private void DoNeighboringPassAsync()
{
SetGraphEnabled(true, true); // set LocateStrategy to Relationship
ResetAnchorIdsToLocate();
SetNearbyAnchor(currentCloudAnchor, 10, numToMake);
locatedCount = 0;
dueDate = DateTime.Now.AddSeconds(30);
currentWatcher = CreateWatcher();
currentAppState = AppState.Neighboring;
}
private void CleanupObjectsBetweenPasses()
{
foreach (GameObject go in allSpawnedObjects)
{
Destroy(go);
}
allSpawnedObjects.Clear();
foreach (Material m in allSpawnedMaterials)
{
Destroy(m);
}
allSpawnedMaterials.Clear();
currentCloudAnchor = null;
spawnedObject = null;
spawnedObjectMat = null;
spawnedObjectsPerAppState.Clear();
anchorIds.Clear();
}
protected override bool IsPlacingObject()
{
throw new NotImplementedException();
}
}
}`
Description
As of a week or two ago, locating spatial anchors using the LocateStrategy.VisualInformation has been exhibiting strange behaviour. We have been using Azure Spatial Anchors for about 12 months and have specified the LocateStrategy as VisualInformation when attempting to locate specific anchors. We have not changed this setting since we started.
About a fortnight ago, we noticed that our application was no longer correctly locating spatial anchors. This occurred on multiple devices (Android & iOS) and for multiple different uploaded spatial anchors.
The strangest thing is that after creating each spatial anchor, we are able to locate 2-4 times (in separate sessions, closing the application between each attempt) - but then that anchor will suddenly stop locating altogether (even on different devices).
This was all working perfectly a couple weeks ago, and this issue seems to have propagated backwards into our older builds as well. After a whole lot of debugging, I discovered that everything seemed to be running as usual but Azure was printing wasRelocalized[0] when trying to locate the anchor as opposed to wasRelocalized[1] on a successful attempt in the following log:
(ASA) ProcessPoseQueryStreamingPoseEvent - naid[id], wasRelocalized[0]
This appears to mean the anchor was unable to relocalize on the server (but I could be wrong). After trying and reverting a bunch of different things on our end, in a last ditch attempt, I swapped the LocateStrategy (which hadn't been touched in about a year) to LocateStrategy.AnyStrategy and all of a sudden all the spatial anchors started locating correctly again.
Was anything changed on your end in regards to how you handle the LocateStrategy.VisualInformation? Is there anything I should be looking at in the ASA logs? I manually compared the full logs of a successful locate to an unsuccessful locate and found it mostly the same other than the above wasRelocalized difference.
Steps to reproduce the issue
The steps we used to reproduce the issue were to:
Expected behavior
We expect spatial anchors to locate correctly as they do the first 2-3 times (and have been consistently before this issue occurred a fortnight ago)
Development information
Issue occured on:
Unity 2019.2.15f1 with Azure Spatial Anchors SDK version v2.2.0 and Unity 2019.4.0f1 with Azure Spatial Anchors SDK version v2.4.0
The problem occurs with builds created from Windows, OSX (XCode) and also with Unity Cloud Build.
AR Device information (please complete the following information):
We have noticed the issue on:
iPhone 6S iPhone X Google Pixel 3A
Additional context
I unfortunately have not had a chance to see if this issue occurs in the Azure Samples yet, but figured I'd open up the issue as we started seeing these problems at about the same time you released ASA v2.4.0. There may be something on our end that is causing this, but we haven't changed anything (and the fact it was visible in older builds is somewhat telling)