# Hit Testing Sample

This sample demonstrates how to hit test against points and planes found in the real world. For basic information about hit testing via raycasts and what AR Foundation's AR Raycast Subsystem component does, please refer to the Unity documentation (opens new window). In order to use this feature it has to be enabled in the OpenXR plugin settings located under Project Settings > XR Plug-in Management > OpenXR (> Android Tab). The wordings ray casting and hit testing are used interchangeably throughout the documentation.

# How the sample works

WARNING

If Use Scene Understanding Plane Detection is enabled in the Plane Detection feature settings, the ARRaycastHit.trackableId field will always return the trackableId of 0-0 as the session-unique identifier for the trackable that was hit. If Use Scene Understanding Plane Detection is disabled, the ARRaycastHit.trackableId will return the trackableIds of the planes that the raycast has hit.

Adding the AR Raycast Manager to the AR Session Origin GameObject will enable the ray casting subsystem. If there is no plane manager available, the Hit Testing feature will create the underlying foundations for hit testing. If a plane manager will be spawned later on, the underlying plane detection subsystem will be adjusted for that manager and hit tracking might work differently (for instance, results depend on the plane filters set on the plane manager). For optimal results, enable all filters on the plane manager, if you use hit testing as well. If you don't use a separate plane manager, the hit testing feature will handle this automatically for best results.

The AR Raycast Manager component provides a field for defining a prefab to spawn upon successfully intersecting with a plane. For this sample, the prefab has been left blank, since this functionality is implemented in the Hit Testing Sample Controller component.

The raycast manager's Raycast function will return a boolean value depending on if the ray has hit a plane or not. The hit result(s) will be added to the ARRaycastHit list, sorted by ascending distance (i.e. closest first).

    public void Update() {
        CastRay();
        _activeIndicator.transform.position = _desiredPosition;
    }

    private void CastRay() {
        Ray ray = new Ray(_cameraTransform.position, _cameraTransform.forward);

        List<ARRaycastHit> hitResults = new List<ARRaycastHit>();
        if (_raycastManager.Raycast(ray, hitResults)) {
            _desiredPosition = hitResults[0].pose.position;
            ...
        }
        else {
            ...
        }
    }

The sample scene has a default red colored gizmo indicator that follows the gaze. Every frame a raycast is created from the origin of the head to the direction of the gaze. If the raycast hits a plane, the indicator gizmo will change color and move to the hit position. If it doesn't hit anything, the indicator gizmo will remain the same.