Unity-Technologies / arfoundation-samples

Example content for Unity projects based on AR Foundation
Other
2.99k stars 1.11k forks source link

[Bug] on iOS, tracking seems unable to retain the tracking status of an Image Target and causes flickering #1030

Closed SimonDarksideJ closed 1 year ago

SimonDarksideJ commented 1 year ago

Unity bug report case number Please log a bug at https://unity3d.com/unity/qa/bug-reporting and post the case number here.

Describe the bug We've been testing for some time now with ARFoundation Image Tracking on Android/ARCore and with only a few exceptions, everything is tracking fine.

However, we used the same project and built it for iOS and observed the following issues:

To Reproduce Steps to reproduce the behavior:

  1. Create a Project configured ARFoundation Image Tracking project
  2. Using the following handler for the OnTrackedImages event
        private void OnTrackedImagesChanged(ARTrackedImagesChangedEventArgs eventArgs)
        {
            // Go through all tracked images that have been added 
            // (-> new markers detected) 
            foreach (var newImage in eventArgs.added)
            {
                if (instantiatedPrefabs.TryGetValue(imageReference, out var instantiatedMarker))
                {
                    OnTrackedImageChanged?.Invoke($"{newImage.referenceImage.name} was found and restored");
                    instantiatedMarker.gameObject.SetActive(newImage.trackingState == TrackingState.Tracking);
                    break;
                }

                foreach (var image in trackedImages)
                {
                    if (image.Name.Equals(newImage.referenceImage.name))
                    {
                        // Found a corresponding prefab for the reference image, and it has not been 
                        // instantiated yet > new instance, with the ARTrackedImage as parent 
                        // (so it will automatically get updated when the marker changes in real life) 
                        GameObject newPrefab = Instantiate(prefabObject, newImage.transform);
                        newPrefab.transform.position = new Vector3(newImage.transform.position.x, newImage.transform.position.y + floating_distance, newImage.transform.position.z);
                        // Store a reference to the created prefab 
                        instantiatedPrefabs.Add(newImage.referenceImage.guid, newPrefab);
                    }
                }
            }

            // Disable instantiated prefabs that are no longer being actively tracked
            foreach (var updatedImage in eventArgs.updated)
            {
                if (instantiatedPrefabs.TryGetValue(updatedImage.referenceImage.guid, out var gameObject))
                {
                    bool isTracked = updatedImage.trackingState == TrackingState.Tracking;
                    if (gameObject.activeSelf != isTracked)
                    {
                        gameObject.SetActive(isTracked);
                    }
                }
            }

            // Remove is called if the subsystem has given up looking for the trackable again.
            // (If it's invisible, its tracking state would just go to limited initially).
            // Note: ARCore doesn't seem to remove these at all; if it does, it would delete our child GameObject
            // as well.
            foreach (var removedImage in eventArgs.removed)
            {
                // Destroy the instance in the scene.
                // Note: this code does not delete the ARTrackedImage parent, which was created
                // by AR Foundation, is managed by it and should therefore also be deleted by AR Foundation.
                if (instantiatedPrefabs.TryGetValue(removedImage.referenceImage.guid, out var gameObject))
                {
                    GameObject.Destroy(gameObject);
                    instantiatedPrefabs.Remove(removedImage.referenceImage.guid);
                }
            }
        }

(InstantiatedPrefabs is just a Dictionary of Prefabs)

        private readonly Dictionary<Guid, GameObject> instantiatedPrefabs = new Dictionary<Guid, GameObject>();
  1. Build and run the sample on iOS
  2. See error/flickering

Expected behavior A clear and concise description of what you expected to happen. Stable tracked prefabs on the Image target.

Actual behavior A clear and concise description of what actually happened.

on iOS, prefab flickers on / off, on Android it is stable.

Smartphone (please complete the following information):

SimonDarksideJ commented 1 year ago

Issue resolved, essentially on Android

So the difference in functionality we were seeing was that the foundation sample only checks for "Tracking State = None" and any other state is valid, where our functionality was dealing with all three states.

The resolution is to fall back to the samples implementation and only deal with the None state and all other states are effectively tracking on all platforms, this resolves flicking on iOS where is seems less sure about tracked images.