Self made collision detection

Hello! I’m new to the forum but I have made a project I would like to share. I wanted to try to make my own collision detection. It’s basically because I want an alternative to the rigidbody tools.

It works by checking each vertex of a mesh if it’s inside the face of another mesh.

It is quite slow right now with the calculations but I would like to improve it.

Video showcase:

https://www.youtube.com/watch?v=pKbwYiEV06c](https://www.youtube.com/watch?v=pKbwYiEV06c)

The first script is called Collidable.gd and does the calculations:

extends MeshInstance3D

#Checks if this object collides with another
func checkCollision(n2):	
	var collided = false
	
	for n in n2:

		var nVerts = n.mesh.surface_get_arrays(0)[Mesh.ARRAY_VERTEX]

		var nInds = n.mesh.surface_get_arrays(0)[Mesh.ARRAY_INDEX]
		 
#This mesh
	        var verts2 = get_child(0).mesh.surface_get_arrays(0)[Mesh.ARRAY_VERTEX]
		
		var i = 0
		while i < nInds.size():
			for v in verts2:
				v *= scale

				if inside(v, i, nInds, nVerts, n):
					collided = true
			i += 3

	return collided
	
	
func inside(v : Vector3, i : int, inds, verts, n):
        #Triangle points
	var a1 = verts[inds[i]] * n.scale
	var b1 = verts[inds[i + 1]] * n.scale
	var c1 = verts[inds[i + 2]] * n.scale
	
	var a = a1 + n.position
	var b
	var c
	
	if a1.distance_to(b1) < a1.distance_to(c1):
		b = b1 + n.position
		c = c1 + n.position
	else:
		b = c1 + n.position
		c = b1 + n.position

	var yTop

        #Getting the highest vertex in the triangle
	if a.y >= b.y and a.y >= c.y:
		yTop = a.y
	elif b.y >= a.y and b.y >=  c.y:
		yTop = b.y
	elif c.y >=  a.y and c.y >=  b.y:
		yTop = c.y
		
	var i2 = 0
	
	v += position
	
        #I tried using the function (delta y) / (delta x)
        #* x to calculate the x and z values at the
        #vertex position. 
	if a.x - b.x > 0:
                #i2 is going along the x axis
		while i2 < abs(a.x - b.x):
			if v.y <= yTop + scale.y:
				if v.x >= a.x + i2 / abs(a.z - c.z) * (v.z - a.z):
					if v.x <= b.x - i2 / abs(a.z - c.z) * (v.z - a.z):
						if a.z - c.z > 0:
							if v.z >= a.z + abs(a.z - c.z) / (i2 + 1) * (v.x - a.x):
								if v.z <= c.z - abs(a.z - c.z) / (i2 + 1) * (v.x - a.x):
									return true
						else:
							if v.z <= a.z - abs(a.z - c.z) / (i2 + 1) * (v.x - a.x):
								if v.z >= c.z + abs(a.z - c.z) / (i2 + 1) * (v.x - a.x):
									return true
			i2 += 1
	else:
		while i2 < abs(a.x - b.x):
			if v.y <= yTop + scale.y:
				if v.x >= a.x - i2 / abs(a.z - c.z) * (v.z - a.z):
					if v.x <= b.x + i2 / abs(a.z - c.z) * (v.z - a.z):
						if a.z - c.z > 0:
							if v.z >= a.z + abs(a.z - c.z) / (i2 + 1) * (v.x - a.x):
								if v.z <= c.z - abs(a.z - c.z) / (i2 + 1) * (v.x - a.x):
									return true
							else:
								if v.z <= a.z - abs(a.z - c.z) / (i2 + 1) * (v.x - a.x):
									if v.z >= c.z + abs(a.z - c.z) / (i2 + 1) * (v.x - a.x):
										return true
			i2 += 1
		return false

It’s quite a lot of code, it’s basically some linear equations with the scale added.

The next script is called Item.gd and is inheriting Collidable. This is the script that is attached to the object to do physics with.

extends "res://Collidable.gd"

var moveDir
@export var speed = 0.5
var ticks = 0

func _ready():
	
	var side = -0.07 + randf() * 0.14
	moveDir = Vector3(side / 3, 0, -0.2)
	
func _process(delta: float) -> void:
    #Slowing down the function calling
	if ticks % 3 == 0:
        
		if checkCollision([get_parent_node_3d().get_child(1)]):
			var rand = Vector3(-0.5 + randf(), 0, -0.5 + randf()) / 20
            #Right now I'm making the object ”bounce” 
            #and also adding a little bit of random
			moveDir = -moveDir + rand
	
	position += moveDir * 0.05 * speed
	ticks += 1

Feel free to share suggestions or ideas.
Hope you found it interesting.

1 Like

How come?

It’s a neat exercise, but if you’re having a particular problem with the physics systems there are lots of things you can do to tweak it. RigidBody3D is only meant for things like balls and grenades really. Other objects are meant for other things.

I see! It’s just adding the bodies to the meshes that I felt took some time.

Tomorrow I think I will check the collision code because the fans on my pc start when the game runs.

Or maybe test the other systems you mentioned.

You’re right, it is if you want a complex shape. But then, you’ve seen the performance hit of moving and testing all those triangles. Unless your game is centered around this object, I recommend using a simpler shape.

1 Like

Yeah testing all the triangles must take quite a lot of power.

Maybe I will put the project aside as a fun exercise and use the Godot collision.

Cool name by the way :slightly_smiling_face:

1 Like