so i’ve been working a dungeon generation script, and i have the basic room generation completed. i am having an issue with moving the parts so that none of them are colliding. i was recommended AABB collision methods, but i am fairly new to collisions and physics so i have absolutely no idea how to implement them. see code examples and the gif below
my basic cell generation
local function spawnCells()
local spawned = 0
for i = 1, gameConfig.cells.amount do
local cell = Instance.new("Part")
cell.CanCollide = false
cell.Anchored = true
local cellSettings = {
size = {
x = math.random(gameConfig.cells.min_sizes.x, gameConfig.cells.max_sizes.x),
z = math.random(gameConfig.cells.min_sizes.z, gameConfig.cells.max_sizes.z)
}
}
cell.Size = Vector3.new(cellSettings.size.x, 1, cellSettings.size.z)
local x, z = getRandomPointInCircle(gameConfig.cells.radius)
cell.Position = Vector3.new(x,1,z)
cell.TopSurface = Enum.SurfaceType.Smooth
cell.Name = "cell"..i
cell.Parent = workspace.dungeon
spawned += 1
task.wait(.1)
end
if spawned == gameConfig.cells.amount then
print("--| rooms generated successfully | checking collisions")
return true, spawned
else
warn("[error] could only generate " .. spawned .. " rooms | check code")
return true, spawned
end
end
any links to articles that may be helpful or some advice would be appreciated, i have been searching for a while now, but they all seem to do with UI
Firstly, there is a difference between collision detection and collision response. For AABB, the concept is generally take your shapes and check if there is overlap when projected on the x axis, then check overlap on the y. The shape is colliding only if both the x and the y (and Z for 3D) overlap tests pass. Of course a collision is only guaranteed in this case because it looks like your shapes are axis aligned boxes.
When you’ve determined your shapes are colliding you need to figure out how you intend to make them not collide. The simplest method is just give them a small force pushing away from what they are colliding with (the center) and just keep doing that until they have all separated. Of course, depending on your specific needs, this step will be different. Like if you want it to favor separating on the x axis, the implantation above won’t be great.
-- Some vector math, for calculating the pos/size of the overlap
local aDir,bDir=(a.Position-b.Position).Unit,(b.Position-a.Position).Unit
local aSign,bSign = Vector3.new(math.sign(aDir.X),math.sign(aDir.Y),math.sign(aDir.Z)),Vector3.new(math.sign(bDir.X),math.sign(bDir.Y),math.sign(bDir.Z))
local aBound,bBound = a.Position-Vector3.new(a.Size.X/2,0,a.Size.Z/2) * aSign,b.Position-Vector3.new(b.Size.X/2,0,b.Size.Z/2) * bSign
local xLength,zLength = math.max((aBound.X-bBound.X),(bBound.X-aBound.X)),math.max((aBound.Z-bBound.Z),(bBound.Z-aBound.Z))
-- Get the lowest and highest X & Z values.
local xMin,xMax = math.max(aBound.X-a.Size.X/2,bBound.X-b.Size.X/2), math.min(aBound.X-a.Size.X/2,bBound.X-b.Size.X/2)
local zMin,zMax = math.max(aBound.Z-a.Size.Z/2,bBound.Z-b.Size.Z/2), math.min(aBound.Z-a.Size.Z/2,bBound.Z-b.Size.Z/2)
-- -- Check if the upper bounds of part 1 are not higher than the lower bounds of part 2, etc.
if aBound.X >= b.Position.X-b.Size.X/2 and aBound.X <= b.Position.X+b.Size.X/2 or aBound.X <= b.Position.X-b.Size.X/2 and aBound.X >= b.Position.X+b.Size.X/2 then
end
if aBound.Z >= b.Position.Z-b.Size.Z/2 and aBound.Z <= b.Position.Z+b.Size.Z/2 or aBound.Z <= b.Position.Z-b.Size.Z/2 and aBound.Z >= b.Position.Z+b.Size.Z/2 then
end