How to Raycast to point and cloud particle in ARFoundation?

I want to know the exact real-world location of a particular point cloud particle. So, I tried to raycast the point cloud particle, but it gives the wrong results.
Here’s my previous workaround:

        if (Input.touchCount > 0 )
        {
            Touch touch = Input.GetTouch(0);
         
            var hits = new List<ARRaycastHit>();
            Ray ray = Camera.main.ScreenPointToRay(touch.position);
            raycastManager.Raycast(ray, hits, TrackableType.FeaturePoint);
            if (Input.touchCount == 1 && Input.GetTouch(0).phase == TouchPhase.Began && PrefabToPlace != null)
            {
                Pose p = hits[0].pose;
                _ShowAndroidToastMessage("Hit at : " + (p.position.z) +  " ciunt L "+ hits.Count);
                var obj = Instantiate(PrefabToPlace, pose.position, pose.rotation);
                obj.name = PrefabToPlace.name;
                obj.transform.parent = ParentAR.transform;

                PrefabToPlace = null;

            }
        }

Please suggest a way to achieve this.

hi everyone ,
i’m still looking for a solution for this problem : knowing the exact real-world location of a particular point cloud particle.
any idea ?
thanks

Here is an example script. Drop references to Raycast Manager and Origin and you’re good to go.

using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using Input = UnityEngine.Input;


namespace ARFoundationRemoteExample.Runtime {
    public class MultiTouchRaycastExample : MonoBehaviour {
        [SerializeField] ARRaycastManager raycastManager = null;
        [SerializeField] ARSessionOrigin origin = null;
        [CanBeNull] [SerializeField] GameObject optionalPointerPrefab = null;
        [SerializeField] bool disablePointersOnTouchEnd = false;
        [SerializeField] TrackableType trackableTypeMask = TrackableType.FeaturePoint;

        readonly Dictionary<int, Transform> pointers = new Dictionary<int, Transform>();


        void Update() {
            for (int i = 0; i < Input.touchCount; i++) {   
                var touch = Input.GetTouch(i);
                var pointer = getPointer(touch.fingerId);
                var touchPhase = touch.phase;
                if (touchPhase == TouchPhase.Ended || touchPhase == TouchPhase.Canceled) {
                    if (disablePointersOnTouchEnd) {
                        pointer.gameObject.SetActive(false);
                    }
                } else {
                    var ray = origin.camera.ScreenPointToRay(touch.position);
                    var hits = new List<ARRaycastHit>();
                    var hasHit = raycastManager.Raycast(ray, hits, trackableTypeMask);
                    if (hasHit) {
                        var pose = hits.First().pose;
                        pointer.position = pose.position;
                        pointer.rotation = pose.rotation;
                    }
                   
                    pointer.gameObject.SetActive(hasHit);
                }
            }
        }

        Transform getPointer(int fingerId) {
            if (pointers.TryGetValue(fingerId, out var existing)) {
                return existing;
            } else {
                var newPointer = createNewPointer();
                pointers[fingerId] = newPointer;
                return newPointer;
            }
        }
       
        Transform createNewPointer() {
            var result = instantiatePointer();
            result.parent = transform;
            return result;
        }

        Transform instantiatePointer() {
            if (optionalPointerPrefab != null) {
                return Instantiate(optionalPointerPrefab).transform;
            } else {
                var result = GameObject.CreatePrimitive(PrimitiveType.Sphere).transform;
                result.localScale = Vector3.one * 0.05f;
                return result;
            }
        }
    }
}