Mateusz
Mateusz

Ray-mesh intersection in Unity Editor

Computing precise mesh intersections is usually prohibitively expensive at runtime0, but it’s still useful for editor scripts and the like. Unity has a built in function for raycasting against a mesh:

UnityEditor.HandleUtility.IntersectRayMesh

Now, if you excuse the fact that it is

  • editor-only1
  • internal
  • unsupported
  • could move
    • or change
    • or break
    • or disappear in any engine update, here’s how you conveniently use it:
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using UnityEngine;
using static System.Reflection.BindingFlags;

public static class MeshFilterExtensions
{
    public static RaycastHit? IntersectRayMesh(this MeshFilter meshFilter, in Ray ray)
        => intersectRayMeshFunc(ray, meshFilter.sharedMesh, meshFilter.transform.localToWorldMatrix, out var result) ? result : null;

    delegate bool IntersectRayMeshDelegate(Ray ray, Mesh mesh, Matrix4x4 matrix, out RaycastHit hit);

    static readonly IntersectRayMeshDelegate intersectRayMeshFunc
        =
#if UNITY_EDITOR
        (IntersectRayMeshDelegate)
        typeof(UnityEditor.HandleUtility)
            .GetMethod("IntersectRayMesh", Static | NonPublic)
            .CreateDelegate(typeof(IntersectRayMeshDelegate));
#else
            null;
#endif
}
0
1
2
3
var ray = new Ray(/* ... */);

if (GetComponent<MeshFilter>().IntersectRayMesh(ray) is { distance: < 1f } hit)
    Debug.Log(hit.collider);

raycasted teapot

  1. If you want to do raycasts at runtime, you’ll want to use simplified collision meshes or approximate your object’s shape using several primitive colliders. Using high-poly mesh colliders will murder your physics engine. return ︿

  2. This trick won’t work at runtime (in player builds).
    The code compiles even in Assembly-CSharp, but you might wanna put this whole thing in Assembly-CSharp-Editor or somewhere instead return ︿