quetty

← Back

Infinite Geometry - Custom collision detection

February 03, 2020

Upgrading a project from 2014 made with Unity 4.6

Infinite Geometry was a game I made in 2014 with Unity 4.6. It was a little game, but i think the core concept of it is quite unique and not like anythink else. I took it down because I didn’t want to pay for another Apple Developer Programm.

But now I want to bring this game back because I feel it was really good and it is one of my first published games.

The first step I took was to upgrade the Project to Unity 2019.3 to meet new requirements by Apple. This conversion required suprisingly littly tweaking as most things stayed the same. The only think that needed updating was the collision detection between the shapes and the player, because non-convex mesh trigger colliders were no longer supported.

My solution to the problem was to just implement my own collision system.

This is the code is used for this. It is basically just a conversion to C# of the code from here.

float SMALL_NUM = 0.00000001f; // anything that avoids division overflow
                                // dot product (3D) which allows vector operations in arguments
                                //#define dot(u,v)   ((u).x * (v).x + (u).y * (v).y + (u).z * (v).z)

[System.Serializable]
public struct Triangle
{
    public Vector3 V0;
    public Vector3 V1;
    public Vector3 V2;
}

[System.Serializable]
public struct Line
{
    public Vector3 P0;
    public Vector3 P1;
}

// intersect3D_RayTriangle(): find the 3D intersection of a ray with a triangle
//    Input:  a ray R, and a triangle T
//    Output: *I = intersection point (when it exists)
//    Return: -1 = triangle is degenerate (a segment or point)
//             0 =  disjoint (no intersect)
//             1 =  intersect in unique point I1
//             2 =  are in the same plane
int intersect3D_RayTriangle(Line R, Triangle T)
{
    Vector3 u, v, n;              // triangle vectors
    Vector3 dir, w0, w;           // ray vectors
    float r, a, b;              // params to calc ray-plane intersect

    // get triangle edge vectors and plane normal
    u = T.V1 - T.V0;
    v = T.V2 - T.V0;
    n = Vector3.Cross(u, v);              // cross product
    if (n == Vector3.zero)             // triangle is degenerate
        return -1;                  // do not deal with this case

    dir = R.P1 - R.P0;              // ray direction vector
    w0 = R.P0 - T.V0;
    a = -Vector3.Dot(n, w0);
    b = Vector3.Dot(n, dir);
    if (Mathf.Abs(b) < SMALL_NUM)
    {     // ray is  parallel to triangle plane
        if (a == 0)                 // ray lies in triangle plane
            return 2;
        else return 0;              // ray disjoint from plane
    }

    // get intersect point of ray with triangle plane
    r = a / b;
    if (r < 0.0)                    // ray goes away from triangle
        return 0;                   // => no intersect
                                    // for a segment, also test if (r > 1.0) => no intersec
    if (r > 1.0)
        return 0;


    Vector3 I = R.P0 + r * dir;            // intersect point of ray and plane

    // is I inside T?
    float uu, uv, vv, wu, wv, D;
    uu = Vector3.Dot(u, u);
    uv = Vector3.Dot(u, v);
    vv = Vector3.Dot(v, v);
    w = I - T.V0;
    wu = Vector3.Dot(w, u);
    wv = Vector3.Dot(w, v);
    D = uv * uv - uu * vv;

    // get and test parametric coords
    float s, t;
    s = (uv * wv - vv * wu) / D;
    if (s < 0.0 || s > 1.0)         // I is outside T
        return 0;
    t = (uv * wu - uu * wv) / D;
    if (t < 0.0 || (s + t) > 1.0)  // I is outside T
        return 0;

    return 1;                       // I is in T
}

After this I just generate a array of triangles from the obstacles and check the camera line segment against the triangles.

Line cameraLine = new Line();

cameraLine.P0 = Camera.main.transform.position;
cameraLine.P1 = Camera.main.transform.position + Camera.main.transform.forward * 2.6f;

Debug.DrawLine(cameraLine.P0, cameraLine.P1);

for (int i = 0; i < triangles.Count; i++)
{
    Triangle tri = new Triangle();

    tri.V0 = transform.TransformPoint(triangles[i].V0);
    tri.V1 = transform.TransformPoint(triangles[i].V1);
    tri.V2 = transform.TransformPoint(triangles[i].V2);
    
    if (intersect3D_RayTriangle(cameraLine, tri) == 1)
    {
        gameOverCon.Hit();
    }
}