Xamarin iOS ARKit - Hittest/RayCast return empty collection in ARSCNView

wuyp 21 Reputation points
2021-01-13T07:11:09.827+00:00

VisualStudio: 8.8.4, Xamarin.iOS: 14.6.
Test Device: iPhone 12 Pro.

I am developing an App with AR features. But I can get nothing when hittest or raycast in ARSCNView.
Following is the key code, the values of 'hitTest' and 'rayCastResult' in function 'PerformHitTest' are always empty collection.
RunSession and PauseSession functions are invoked in another partial class file. 'SessionDidAddAnchors', 'SessionDidUpdateAnchor' and 'SessionDidRemoveAnchor' functions work well.
Someone knows what I am missing?

using System;
using ARKit;
using CoreFoundation;
using CoreGraphics;
using Foundation;
using SceneKit;
using UIKit;

namespace ARTestApplication
{
    public partial class ViewController : IARSessionDelegate, IARSCNViewDelegate
    {
        private void SetupSceneView()
        {
            _session.Delegate = this;

            _sceneView.Session = _session;
            _sceneView.Delegate = this;
            _sceneView.PreferredFramesPerSecond = 60;
        }

        private void RunSession()
        {
            var detection = UIDevice.CurrentDevice.CheckSystemVersion(11, 0) ?
                ARPlaneDetection.Horizontal | ARPlaneDetection.Vertical :
                ARPlaneDetection.Horizontal;
            var configuration = new ARWorldTrackingConfiguration
            {
                PlaneDetection = detection
            };
            _session.Run(configuration, ARSessionRunOptions.RemoveExistingAnchors | ARSessionRunOptions.ResetTracking);
        }

        private void PauseSession()
        {
            _session.Pause();
        }

        private void PerformHitTest()
        {
            var screenCenter = new CGPoint(_sceneView.Bounds.GetMidX(), _sceneView.Bounds.GetMidY());
            Console.WriteLine($"screenCenter: {screenCenter}");

            var hitTest = _sceneView.HitTest(screenCenter, ARHitTestResultType.ExistingPlane);
            Console.WriteLine($"hitTest: {hitTest}");

            var query = _sceneView.CreateRaycastQuery(screenCenter, ARRaycastTarget.EstimatedPlane, ARRaycastTargetAlignment.Any);
            if (null != query)
            {
                var rayCastResult = _sceneView.Session.Raycast(query);
                Console.WriteLine($"rayCastResult: {rayCastResult}");
            }
        }

        #region IARSessionDelegate
        [Export("session:didAddAnchors:")]
        public void SessionDidAddAnchors(ARSession session, ARAnchor[] anchors)
        {
            Console.WriteLine("SessionDidAddAnchors");
        }

        [Export("session:didUpdateAnchors:")]
        public void SessionDidUpdateAnchor(ARSession session, ARAnchor[] anchors)
        {
            Console.WriteLine("SessionDidUpdateAnchor");
        }

        [Export("session:didRemoveAnchors:")]
        public void SessionDidRemoveAnchor(ARSession session, ARAnchor[] anchors)
        {
            Console.WriteLine("SessionDidRemoveAnchor");
        }
        #endregion

        #region IARSCNViewDelegate
        [Export("renderer:didAddNode:forAnchor:")]
        public void DidAddNode(ISCNSceneRenderer renderer, SceneKit.SCNNode node, ARAnchor anchor)
        {
        }

        [Export("renderer:didUpdateNode:forAnchor:")]
        public void DidUpdateNode(ISCNSceneRenderer renderer, SceneKit.SCNNode node, ARAnchor anchor)
        {
        }

        [Export("renderer:didRemoveNode:forAnchor:")]
        public void DidRemoveNode(ISCNSceneRenderer renderer, SceneKit.SCNNode node, ARAnchor anchor)
        {
        }

        [Export("renderer:updateAtTime:")]
        public void RendererUpdateAtTime(SCNSceneRenderer renderer, double updateAtTime)
        {
            Console.WriteLine("RendererUpdateAtTime");
            DispatchQueue.MainQueue.DispatchAsync(() =>
            {
                PerformHitTest();
            });
        }
        #endregion
    }
}
Xamarin
Xamarin
A Microsoft open-source app platform for building Android and iOS apps with .NET and C#.
5,366 questions
{count} votes

Accepted answer
  1. Joe Harvey - MSFT 76 Reputation points
    2021-02-04T20:46:29.127+00:00
     var hitTest = _sceneView.HitTest(screenCenter, ARHitTestResultType.ExistingPlane);
                 Console.WriteLine($"hitTest: {hitTest}");
    
                 var query = _sceneView.CreateRaycastQuery(screenCenter, ARRaycastTarget.EstimatedPlane, ARRaycastTargetAlignment.Any);
                 if (null != query)
                 {
                     var rayCastResult = _sceneView.Session.Raycast(query);
                     Console.WriteLine($"rayCastResult: {rayCastResult}");
                 }
    

    I wanted to make a quick suggestion here. I think you have an error in your code.
    Try the following and you should see results.

    var hitTest = _sceneView.HitTest(screenCenter, ARHitTestResultType.ExistingPlane);
     if(hitTest.Length == 1)
                {
     Console.WriteLine($"hitTest: {hitTest[0].Description}");
     }
    
     var query = _sceneView.CreateRaycastQuery(screenCenter, ARRaycastTarget.EstimatedPlane, ARRaycastTargetAlignment.Any);
     if (null != query)
     {
     var rayCastResult = _sceneView.Session.Raycast(query);
    
     if (rayCastResult.Length == 1)
     {
     Console.WriteLine($"rayCastResult: {rayCastResult[0].Description}");
     }
    
     }
    

    You're code style would work in Objective-C, as that language will write a value for an Array that is posted as a string, would be the equivalent of a custom "toString" for an array. C# will only post "ArrayName []" regardless of content, which is what you are seeing.

    0 comments No comments

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.