How do I get the boundaries of a plane I spawned a gameobject on?

Hi guys!

I am new here :slightly_smiling_face:

I am spawning a vehicle on a plane, and trying to figure out on what plane it was spawned and saving its boundaries. e.g. lowest and highest x,y and z coordinates of the plane the vehicle was spawned on.

I am attaching my code. I will appreciate your help very much!

P.S. I am also including my code achieving the behavior I am looking for with AR Foundation and ARCore (Commented out).

using System.Collections.Generic;

using Niantic.ARDK.AR;
using Niantic.ARDK.AR.ARSessionEventArgs;
using Niantic.ARDK.AR.HitTest;
using Niantic.ARDK.External;
using Niantic.ARDK.Utilities;
using Niantic.ARDK.Utilities.Input.Legacy;

using UnityEngine;
using UniRx;
using TMPro;

///


/// Responsible for placing the object on a plane
///

public class PlacementOnPlane : MonoBehaviour
{
///
/// The camera used to render the scene. Used to get the center of the screen.
///

public Camera Camera = null;

/// The types of hit test results to filter against when performing a hit test.
[EnumFlagAttribute]
public ARHitTestResultType HitTestType = ARHitTestResultType.ExistingPlane;

/// Internal reference to the session, used to get the current frame to hit test against.
private IARSession _session;

/// <summary>
/// Minimum boundary of the spawned plane
/// </summary>
public Vector3 MinBounds { get; private set; }

/// <summary>
/// Maximum boundary of the spawned plane
/// </summary>
public Vector3 MaxBounds { get; private set; }

/// <summary>
/// Bool reactive property that checks if we would like to place the object
/// todo: Change to false
/// </summary>
public ReactiveProperty<bool> IsReadyToPlace { get; private set; } =
    new ReactiveProperty<bool>(true);

/// <summary>
/// The object we will spawn
/// </summary>
[SerializeField] private AffectedObject _objectToSpawn;

/// <summary>
/// Prints values to the canvas.
/// </summary>
public TextMeshProUGUI DebugText = null;

private void Start()
{
    ARSessionFactory.SessionInitialized += OnAnyARSessionDidInitialize;
}

private void OnAnyARSessionDidInitialize(AnyARSessionInitializedArgs args)
{
    _session = args.Session;
}

private void Update()
{
    if (_session == null)
    {
        return;
    }

    if (PlatformAgnosticInput.touchCount <= 0)
    {
        return;
    }

    var touch = PlatformAgnosticInput.GetTouch(0);
    if (touch.phase == TouchPhase.Began)
    {
        TouchBegan(touch);
    }
}

private void TouchBegan(Touch touch)
{
    var currentFrame = _session.CurrentFrame;

    if (currentFrame == null)
    {
        return;
    }

    if (touch.IsTouchOverUIObject())
    {
        Debug.Log("Pressed on UI");
        return;
    }
        
    var results = currentFrame.HitTest
    (
      Camera.pixelWidth,
      Camera.pixelHeight,
      touch.position,
      HitTestType
    );

    int count = results.Count;
    Debug.Log("Hit test results: " + count);

    if (count <= 0)
    {
        Debug.LogWarning("Non-Positive hits");
        return;
    }
        

    // Get the closest result
    var result = results[0];

    Debug.Log($"{result.GetType()}");

    var hitPosition = result.WorldTransform.ToPosition();

    if (!_objectToSpawn.gameObject.activeSelf)
    {
        _objectToSpawn.Spawn();

        //todo: Find the plane on which the raycast was  hit, to set _spawnedPlane
        /**
        // Set _spawnedPlane to the plane that was hit
                        _spawnedPlane = _hits[0].trackable as ARPlane;

                        // Calculate and set _minBounds and _maxBounds based on the boundaries of the spawned plane
                        CalculatePlaneBounds(_spawnedPlane);
         */

        _objectToSpawn.transform.position = hitPosition;

        ObjectPositionPrinter();

        SetObjectPlacingMode();
    }

    /**
    // Raycast hit a plane, spawn the object at the hit position
                Pose hitPose = _hits[0].pose;

                if (!_objectToSpawn.gameObject.activeSelf)
                {
                    _objectToSpawn.Spawn();

                    // Set _spawnedPlane to the plane that was hit
                    _spawnedPlane = _hits[0].trackable as ARPlane;

                    // Calculate and set _minBounds and _maxBounds based on the boundaries of the spawned plane
                    CalculatePlaneBounds(_spawnedPlane);

                    _objectToSpawn.transform.position = hitPose.position;

                    ObjectPositionPrinter();

                    SetObjectPlacingMode();
                }
     */
}

/// <summary>
/// Responsible for determining if we can place an object
/// </summary>
public void SetObjectPlacingMode()
{
    if (IsReadyToPlace.Value)
    {
        IsReadyToPlace.Value = false;
    }
    else
    {
        if (_objectToSpawn.gameObject.activeSelf)
        {
            _objectToSpawn.Dispose();
        }

        IsReadyToPlace.Value = true;
    }
}

/// <summary>
/// Printing the position of the object.
/// </summary>
private void ObjectPositionPrinter()
{
    if (_objectToSpawn.gameObject.activeSelf)
    {
        DebugText.text = $"{_objectToSpawn.transform.position}";
    }
    else
    {
        DebugText.text = $"Still null.";
    }

    DebugText.text = $"Object position: {_objectToSpawn.transform.position}\n " +
        $"Min X:{MinBounds.x}. Max X:{MaxBounds.x} MinZ:{MinBounds.z} MaxZ:{MaxBounds.z}";
}

/// <summary>
/// Calculate the boundaries of the spawned plane
/// </summary>
//private void CalculatePlaneBounds(ARPlane plane)
//{
//    // Get the center of the plane
//    Vector3 center = plane.center;

//    // Get the extents of the plane (half of its size in each dimension)
//    Vector2 extents = plane.extents;

//    // Calculate the minimum and maximum bounds of the plane
//    MinBounds = center - new Vector3(extents.x, 0, extents.y);
//    MaxBounds = center + new Vector3(extents.x, 0, extents.y);

//}

}

/**
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.XR.ARSubsystems;
using TMPro;
using UniRx;

///


/// Responsible for placing the object on a plane
///

public class PlacementOnPlane : MonoBehaviour
{
///
/// The object we will spawn
///

[SerializeField] private AffectedObject _objectToSpawn;

/// <summary>
/// Reference to the raycast manager
/// </summary>
private ARRaycastManager _raycastManager;

/// <summary>
/// Data Structure of the AR Raycast Hits
/// </summary>
private List<ARRaycastHit> _hits = new List<ARRaycastHit>();

/// <summary>
/// Bool reactive property that checks if we would like to place the object
/// </summary>
public ReactiveProperty<bool> IsReadyToPlace { get; private set; } =
    new ReactiveProperty<bool>(false);

/// <summary>
/// Prints values to the canvas.
/// </summary>
public TextMeshProUGUI DebugText = null;

/// <summary>
/// Store the reference to the plane where the vehicle was spawned
/// </summary>
private ARPlane _spawnedPlane;

/// <summary>
/// Minimum boundary of the spawned plane
/// </summary>
public Vector3 MinBounds { get; private set; }

/// <summary>
/// Maximum boundary of the spawned plane
/// </summary>
public Vector3 MaxBounds { get; private set; }

private void Awake()
{
    _raycastManager = GetComponent<ARRaycastManager>();
}

/// <summary>
/// Implementing the main AR logic
/// </summary>
void Update()
{
    if ((Input.touchCount > 0) && (IsReadyToPlace.Value))
    {
        Touch touch = Input.GetTouch(0);

        if (touch.phase == TouchPhase.Began)
        {
            if (_raycastManager.Raycast(touch.position, _hits, TrackableType.PlaneWithinPolygon))
            {
                // Raycast hit a plane, spawn the object at the hit position
                Pose hitPose = _hits[0].pose;

                if (!_objectToSpawn.gameObject.activeSelf)
                {
                    _objectToSpawn.Spawn();

                    // Set _spawnedPlane to the plane that was hit
                    _spawnedPlane = _hits[0].trackable as ARPlane;

                    // Calculate and set _minBounds and _maxBounds based on the boundaries of the spawned plane
                    CalculatePlaneBounds(_spawnedPlane);

                    _objectToSpawn.transform.position = hitPose.position;

                    ObjectPositionPrinter();

                    SetObjectPlacingMode();
                }
            }
        }
    }
}

/// <summary>
/// Calculate the boundaries of the spawned plane
/// </summary>
private void CalculatePlaneBounds(ARPlane plane)
{
    // Get the center of the plane
    Vector3 center = plane.center;

    // Get the extents of the plane (half of its size in each dimension)
    Vector2 extents = plane.extents;

    // Calculate the minimum and maximum bounds of the plane
    MinBounds = center - new Vector3(extents.x, 0, extents.y);
    MaxBounds = center + new Vector3(extents.x, 0, extents.y);

}

/// <summary>
/// Printing the position of the object.
/// </summary>
private void ObjectPositionPrinter()
{
    if (_objectToSpawn.gameObject.activeSelf)
    {
        DebugText.text = $"{_objectToSpawn.transform.position}";
    }
    else
    {
        DebugText.text = $"Still null.";
    }

    DebugText.text = $"Object position: {_objectToSpawn.transform.position}\n " +
        $"Min X:{MinBounds.x}. Max X:{MaxBounds.x} MinZ:{MinBounds.z} MaxZ:{MaxBounds.z}";
}

/// <summary>
/// Responsible for determining if we can place an object
/// </summary>
public void SetObjectPlacingMode()
{
    if (IsReadyToPlace.Value)
    {
        IsReadyToPlace.Value = false;
    }
    else
    {
        if (_objectToSpawn.gameObject.activeSelf)
        {
            _objectToSpawn.Dispose();
        }

        IsReadyToPlace.Value = true;
    }
}

}
*/