Trouble with car collision system

i was looking for this system and ended up finding this thread

i modded his code into my version

local function Collide(part, hitPart)
	if hitPart and hitPart.CanCollide then
		if not (hitPart:IsDescendantOf(car) or hitPart:IsDescendantOf(workspace.PowerupDebris)) and math.abs(hitPart.Position.Y - part.Position.Y) < 1 then
			local carModel = GetEntireModel(hitPart)
			if carModel and carModel:FindFirstChild("DriveSeat") then
				if (tick() - carCollisionDebounce) > 0.1 then
					carCollisionDebounce = tick()
					if car.Chassis.Velocity.magnitude > stats.CollisionVelocity.Car.Min.Value then
						-- Find the position, normal and surface of the hit to pass back for some kind of impact on that part etc
						local _, pos, normal = workspace:FindPartOnRayWithWhitelist(
							Ray.new(part.Position, (hitPart.Position - part.Position).unit * (hitPart.Position - part.Position).magnitude),
							{hitPart}
						)
						car.DriveSeat.Collide:Play()
						print("Collided")
					elseif car.Chassis.Velocity.magnitude > stats.CollisionVelocity.Car.Max.Value then
						-- Find the position, normal and surface of the hit to pass back for some kind of impact on that part etc
						local _, pos, normal = workspace:FindPartOnRayWithWhitelist(
							Ray.new(part.Position, (hitPart.Position - part.Position).unit * (hitPart.Position - part.Position).magnitude),
							{hitPart}
						)
						car.DriveSeat.Crash:Play()
						print("Crashed")
					end
				end
			else
				if (tick() - collisionDebounce) > 1 then
					collisionDebounce = tick()
					if car.Chassis.Velocity.magnitude > stats.CollisionVelocity.Normal.Min.Value then
						-- Find the position, normal and surface of the hit to pass back for some kind of impact on that part etc
						local _, pos, normal = workspace:FindPartOnRayWithWhitelist(
							Ray.new(part.Position, (hitPart.Position - part.Position).unit * (hitPart.Position - part.Position).magnitude),
							{hitPart}
						)
						car.DriveSeat.Collide:Play()
						print("Collided")
					elseif car.Chassis.Velocity.magnitude > stats.CollisionVelocity.Normal.Max.Value then
						-- Find the position, normal and surface of the hit to pass back for some kind of impact on that part etc
						local _, pos, normal = workspace:FindPartOnRayWithWhitelist(
							Ray.new(part.Position, (hitPart.Position - part.Position).unit * (hitPart.Position - part.Position).magnitude),
							{hitPart}
						)
						car.DriveSeat.Crash:Play()
						print("Crashed")
					end
				end
			end
		end
	end
end

my expectation is that system should be determining if any car’s part collides with another part on the horizontal side. But in reality, the system doesn’t do very well so here are the flaws:

1 Like

For this part, yeah it seems unreliable for detecting horizontal touches especially depending the parts size and how it was built then the position will be scaled way up.

Raycasting with the normal angle should be a better option to detect if the part surface is horizontal when measured with the up vector. If it’s up then the angle will be somewhere around 90 degrees.

local function AngleBetween(vector1, vector2)
	return math.acos(math.clamp(vector1.Unit:Dot(vector2.Unit), -1, 1))
end

local function detectPartSlope()
	local UpVector = Vector3.new(0,1,0)

	local rayPos = --from part to part
	local rayDir = 
	local rayResult = workspace:Raycast(rayPos,rayDir)
	if rayResult then
		local angleOfElevation = AngleBetween(rayResult.Normal,UpVector)
		angleOfElevation = math.deg(angleOfElevation)
		return angleOfElevation
	else
		warn("Ray result not found")
		return 45--random number
	end

Not sure about the velocity criteria, just hope this helps for now.

1 Like

hmm, before you posted this, i had found a solution that’s the same as yours but pretty different in like this:
instead of calculating angle/slope, you can create multiple rays that form a ring, the ring can be described as a raycast hitbox, if one of rays hits surrounding part, it triggers collide function. Here’s how the code looks like

Thread:Spawn(function()
	local numrings = 8
	--Body cast
	for y = 0, 1 do
		for x = 0, numrings - 1 do
			local direction = (car.Chassis.CFrame * CFrame.Angles(0, x / numrings * math.pi * 2,0)).LookVector
			CollideRay(direction * stats.CollideRadius.Value)
		end
	end
end)

so ye, the result was nice
btw, thank you for your advice : P

edit: i also fixed velocity criteria by replacing elseif to else → if

1 Like