Search Unity

Bug Unable to sync Anchors in iOS with collaborative session

Discussion in 'AR' started by OnTopStudios, Feb 28, 2023.

  1. OnTopStudios

    OnTopStudios

    Joined:
    Aug 19, 2013
    Posts:
    44
    Hello,

    I've followed this tutorial to create a collaborative session in iOS:


    So far so good, everything works.

    Now that I've tried to do the same in my project, everything works normally except for the anchor placement. The master places anchors, the client receives the data as bytes, but the anchor manager doesn't spawn the anchor as it should.

    Code (CSharp):
    1. protected override void OnEnable()
    2.     {
    3.         base.OnEnable();
    4.  
    5.         _arAnchorManager.anchorsChanged += UpdateAnchors;
    6.     }
    7.  
    8.  
    9. private void UpdateAnchors(ARAnchorsChangedEventArgs args)
    10.     {
    11.         if (args.added != null && args.added.Count > 0)
    12.         {
    13.             Debug.Log("Anchor added!");
    14.             if (!_receivedAnchor)
    15.             {
    16.                 NetworkManager.Instance.SetLocalPlayerReady(true);
    17.                 _infinitePlaneManager.SetARPlanesVisibility(false);
    18.             }
    19.  
    20.             _receivedAnchor = true;
    21.         }
    22.  
    23.         if (args.updated != null && args.updated.Count > 0)
    24.         {
    25.             Debug.Log("Anchor updated!");
    26.             if (!_receivedAnchor)
    27.             {
    28.                 NetworkManager.Instance.SetLocalPlayerReady(true);
    29.                 _infinitePlaneManager.SetARPlanesVisibility(false);
    30.             }
    31.  
    32.             _receivedAnchor = true;
    33.         }
    34.     }

    I'm using ARFoundation with ARKit 4.2.7 and Unity 2021.3.6f1, the same versions as the working example that I've got.

    Has anyone stumbled upon something like this?

    Regards and thank you!
     
  2. OnTopStudios

    OnTopStudios

    Joined:
    Aug 19, 2013
    Posts:
    44
    Issue solved, but it took me some long hours to figure out.

    I wanted to only use planes as the Raycast targets. In the previous sample, it used both planes and point cloud raycasts.
    In the AnchorCreator from that example, there are 2 wait to place anchors: from a detected plane and from a point cloud point:

    Code (CSharp):
    1.      ARAnchor CreateAnchor(in ARRaycastHit hit)
    2.         {
    3.             ARAnchor anchor = null;
    4.  
    5.             var pose = hit.pose;
    6.             pose.rotation = Quaternion.Euler(Vector3.up * Camera.main.transform.eulerAngles.y);
    7.  
    8.             // If we hit a plane, try to "attach" the anchor to the plane
    9.             if (hit.trackable is ARPlane plane)
    10.             {
    11.                 var planeManager = GetComponent<ARPlaneManager>();
    12.                 if (planeManager != null)
    13.                 {
    14.                     Debug.Log("Creating anchor attachment.");
    15.  
    16.                     if (m_Prefab != null)
    17.                     {
    18.                         var oldPrefab = m_AnchorManager.anchorPrefab;
    19.                         m_AnchorManager.anchorPrefab = m_Prefab;
    20.                         anchor = m_AnchorManager.AttachAnchor(plane, pose);
    21.                         m_AnchorManager.anchorPrefab = oldPrefab;
    22.                     }
    23.                     else
    24.                     {
    25.                         anchor = m_AnchorManager.AttachAnchor(plane, pose);
    26.                     }
    27.  
    28.                     //SetAnchorText(anchor, $"Attached to plane {plane.trackableId}");
    29.                     return anchor;
    30.                 }
    31.             }
    32. #if !UNITY_EDITOR
    33.             else
    34.             {
    35.                 Debug.Log("Must hit an ARPlane");
    36.                 return null;
    37.             }
    38. #endif
    39.  
    40.             // Otherwise, just create a regular anchor at the hit pose
    41.             Debug.Log("Creating regular anchor.");
    42.  
    43.             if (m_Prefab != null)
    44.             {
    45.                 // Note: the anchor can be anywhere in the scene hierarchy
    46.                 var gameObject = Instantiate(m_Prefab, pose.position, pose.rotation);
    47.                 // Make sure the new GameObject has an ARAnchor component
    48.                 anchor = gameObject.AddComponent<ARAnchor>();
    49.             }
    50.             else
    51.             {
    52.                 var gameObject = new GameObject("Anchor");
    53.                 gameObject.transform.SetPositionAndRotation(pose.position, pose.rotation);
    54.                 anchor = gameObject.AddComponent<ARAnchor>();
    55.             }
    56.  
    57.             return anchor;
    58.         }

    These are NOT the same thing:
    anchor = m_AnchorManager.AttachAnchor(plane, pose);
    anchor = gameObject.AddComponent<ARAnchor>();



    The first line creates an anchor, but it doens't share it on a collaborative session. Maybe it's a Unity bug?

    In any case, I'm just leaving the solution here in case someone else stumbles upon the same problem. Just remove the AR Plane check section.


    Code (CSharp):
    1.  ARAnchor CreateAnchor(in ARRaycastHit hit)
    2.         {
    3.             ARAnchor anchor = null;
    4.  
    5.             var pose = hit.pose;
    6.             pose.rotation = Quaternion.Euler(Vector3.up * Camera.main.transform.eulerAngles.y);
    7.  
    8.             Debug.Log("Creating regular anchor.");
    9.  
    10.             if (m_Prefab != null)
    11.             {
    12.                 // Note: the anchor can be anywhere in the scene hierarchy
    13.                 var gameObject = Instantiate(m_Prefab, pose.position, pose.rotation);
    14.                 // Make sure the new GameObject has an ARAnchor component
    15.                 anchor = gameObject.AddComponent<ARAnchor>();
    16.             }
    17.             else
    18.             {
    19.                 var gameObject = new GameObject("Anchor");
    20.                 gameObject.transform.SetPositionAndRotation(pose.position, pose.rotation);
    21.                 anchor = gameObject.AddComponent<ARAnchor>();
    22.             }
    23.  
    24.             return anchor;
    25.         }
     
    andyb-unity likes this.