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();
}
}