So this is what I've got going. On account of the inquiries of @DMGregory, I managed to file down exactly what I needed to test for. It's likely that I'll do something a little different, but this seems to work:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter))]
public class TriangleReport : MonoBehaviour {
GameManager manager;
Mesh mesh;
int[] triangles;
Vector3[] vertices;
Vector3[] normals;
Plane Left, Right, Top, Bottom;
void Awake() {
manager = GameObject.Find("/Game Manager").GetComponent<GameManager>();
}
///<summary>
///I will only ever need to worry about the top, bottom, left, and right of the mesh bounds, which will be z-axis aligned.
///That said, I can compare the normals of the triangles to the Left/Up/Right/Down normals and find the ones that best fit. Since
///one triangle defines a plane, this will be all I need to simply do a minimum of plane distances.
///</summary>
void Start () {
mesh = GetComponent<MeshFilter>().mesh;
triangles = mesh.triangles;
normals = mesh.normals;
vertices = mesh.vertices;
Vector3[] RightVerts = GetFaceAligned(vertices, triangles, normals, Vector3.right);
Vector3[] LeftVerts = GetFaceAligned(vertices, triangles, normals, Vector3.left);
Vector3[] TopVerts = GetFaceAligned(vertices, triangles, normals, Vector3.up);
Vector3[] BottomVerts = GetFaceAligned(vertices, triangles, normals, Vector3.down);
//Get normal of the triangle via a cross product (either direction will do)
Vector3 NormalRight = Vector3.Cross(RightVerts[1] - RightVerts[0], RightVerts[2] - RightVerts[0]).normalized;
Vector3 NormalLeft = Vector3.Cross(LeftVerts[1] - LeftVerts[0], LeftVerts[2] - LeftVerts[0]).normalized;
Vector3 NormalTop = Vector3.Cross(TopVerts[1] - TopVerts[0], TopVerts[2] - TopVerts[0]).normalized;
Vector3 NormalBottom = Vector3.Cross(BottomVerts[1] - BottomVerts[0], BottomVerts[2] - BottomVerts[0]).normalized;
Right = new Plane(RightVerts[0], NormalRight);
Left = new Plane(LeftVerts[0], NormalLeft);
Top = new Plane(TopVerts[0], NormalTop);
Bottom = new Plane(BottomVerts[0], NormalBottom);
}
///<summary>
///Find the triangle that best matches the provided normal, and return it
///</summary>
Vector3[] GetFaceAligned(Vector3[] vertices, int[] triangles, Vector3[] normals, Vector3 bestNormal) {
int winner = -1;
float winningDot = System.Single.NegativeInfinity;
for(int i = 0; i < triangles.Length; i += 3) {
Vector3 normal = (normals[triangles[i]] + normals[triangles[i+1]] + normals[triangles[i+2]])/3f;
float dot = Vector3.Dot(normal, bestNormal);
if(dot > winningDot) {
winningDot = dot;
winner = i;
}
}
return new Vector3[3]{
vertices[triangles[winner]],
vertices[triangles[winner + 1]],
vertices[triangles[winner + 2]]
};
}
// Update is called once per frame
void OnTriggerStay (Collider c) {
Vector3 pos = transform.InverseTransformPoint(manager.robot.transform.position);
float distance = Mathf.Min(Bottom.GetDistanceToPoint(pos),
Mathf.Min(Top.GetDistanceToPoint(pos),
Mathf.Min(Left.GetDistanceToPoint(pos),
Right.GetDistanceToPoint(pos))));
Debug.Log(distance);
}
}
That said, what I do is compare each triangle's effective normal to the direction I'm looking for, and select the one that has the highest (and most congruent) dot product. This would be the one that "best" faces that direction.
Since all a plane needs is three vertices and a normal, and in this instance either normal would work, all I have to do to get a plane is take the cross product of two vectors along the triangle.
Plane has a convenient GetDistanceToPoint
method which will provide the distance to a Vector3 to me. To determine the shortest path out, or at least, its length, all I have to do is take the minimum.
Looking back, there is easily a better way to find the minimum of four items... but this works well as a P.o.C.
@DMGregory also pointed out that I'm effectively, at least in this instance, trying to find the distance to the edge of a 2D trapezoid; but this might not always be true for this project. (We'll see.) I hope this helps someone.