I’m doing a raycast hit test against a trackable type of plane, however I would also like to see if the plane is vertical or horizontal as I want to do different things based on if the plane is vertical or horizontal, but trackable types doesnt seem to make this destinction…
If you have a reference to the ARPlane, you can check the alignment with the ARPlane.alignment property.
To get a reference to the ARPlane from the raycast, you can look at the TrackableType to know what kind of trackable you hit, then ask the corresponding manager for that trackable passing in the ARRaycastHit.trackableId.
For classification you can do something like the following:
// plane is a reference to the ARPlane
if ((plane.classifications & PlaneClassifications.WallFace) != 0)
{
// the plane is a wall face
}
You could swap between alignments at runtime but it has different behavior depending on the platform. All it guarantees is that the manager will stop detecting any new planes that do not match the set alignment. It doesn’t mean that any already discovered planes that don’t match will be removed.
I have this in my Update function, but it seems to never print my messages of Wall or Floor to the console so I’m not sure things are working as I expect:
void Update()
{
if (aRRaycastManager.Raycast(new Vector2(Screen.width / 2, Screen.height / 2), hits, TrackableType.PlaneWithinPolygon))
{
TrackableId _planeID = hits[0].trackableId;
ARPlane _arPlane = arPlaneManager.GetPlane(_planeID);
// plane is a reference to the ARPlane
if ((_arPlane.classifications & PlaneClassifications.Floor) != 0)
{
// the plane is a wall face
Debug.Log("Floor!!!");
}
// plane is a reference to the ARPlane
if ((_arPlane.classifications & PlaneClassifications.WallFace) != 0)
{
// the plane is a wall face
Debug.Log("Wall!!!");
}
}
}
Something is not right here and I dont know if its just because I’m running the test in the XR Simulation environment or what, but the plane clasification is always “NONE” on any plane of trackabletype PlaneWithinPolygon
I couldnt get the classifications to work for unknown reasons. Would be great if somebody could help me out with that.
In the meantime, the plane’s normal seems to do the job:
if (_arPlane.normal.y == 1)
{
// the plane is a Floor face
Debug.Log("Floor!!!");
}
if (_arPlane.normal.x == -1 || _arPlane.normal.x == 1 || _arPlane.normal.z == -1 || _arPlane.normal.z == 1)
{
// the plane is a Wall face
Debug.Log("Wall!!!");
}
You shouldn’t use the == operator to compare floats for equality. Due to the nature of floating point precision, the resulting behavior is often not what you intend. Use Mathf.Approxmiately instead: Unity - Scripting API: Mathf.Approximately
…however, even though this now finally works in the XR simulator, it doesnt seem to work at all in the real world if I build to my iOS device, it never detects any walls with that if statement…
ah yes I see now what is going on
since the XR simulation has all the walls to exact 90 degree angles to the parallel to the grid, then the code in my if statement works perfectly fine.
However in the real world, you’r hardly ever standing exactly parralel to a wall etc, so instead of the normal reading that “1.00, 0.00, 1.0f” value, it’s more some odd value depending on the angle like for example “0.67, 0,00 -0.23” etc
There is, if you know some math :). I asked Chat GPT to write some sample code for you.
using UnityEngine;
public class VectorUtility : MonoBehaviour
{
/// <summary>
/// Checks if the given normalized vector is within 1 degree of being parallel to the ground.
/// </summary>
/// <param name="normalizedVector">The normalized vector to check.</param>
/// <returns>True if the vector is within 1 degree of being parallel to the ground, false otherwise.</returns>
public bool IsVectorParallelToGround(Vector3 normalizedVector)
{
// Ensure the vector is normalized
if (normalizedVector.magnitude != 1.0f)
{
Debug.LogError("The input vector is not normalized.");
return false;
}
// Vector parallel to the ground will have a Y component close to 0
float yComponent = Mathf.Abs(normalizedVector.y);
// Calculate the angle in degrees between the vector and the XZ plane
float angle = Mathf.Asin(yComponent) * Mathf.Rad2Deg;
// Check if the angle is within 1 degree
return angle <= 1.0f;
}
}
Explanation:
Normalization Check: Ensure the vector is normalized by checking if its magnitude is 1.0. If it’s not normalized, it logs an error and returns false.
Y Component Calculation: The absolute value of the Y component of the vector is taken because we are only interested in the magnitude of the deviation from the horizontal plane, not the direction (above or below the plane).
Angle Calculation: The angle between the vector and the horizontal plane (XZ plane) is calculated using Mathf.Asin(yComponent). Since Mathf.Asin returns the result in radians, it is converted to degrees by multiplying by Mathf.Rad2Deg.
Angle Check: The method checks if this angle is less than or equal to 1 degree. If it is, the vector is considered to be within 1 degree of being parallel to the ground.
Usage:
You can use this method by attaching the VectorUtility script to a GameObject in your Unity scene and calling the IsVectorParallelToGround method with the normalized vector you want to check.