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.