Custom Character Controller Collision Response Algorithm

Hey bois.

I’ve been working on a character controller for the past few weeks and found an algorithm to handle horizontal collision response but it’s not working properly as it allows the player to go through walls when walking towards it at certain angles, here’s a preview of what it looks like in action:

I’m not sure if it has to do with the way I project the velocity vector or perhaps even with floating point errors accumilating, here is the code that adjusts the horizontal velocity based on collision:

local function projectOnPlane(vector: Vector3, planeNormal: Vector3)
	local dotProduct = vector:Dot(planeNormal)
	return (vector - (dotProduct * planeNormal))
end

local function projectAndScale(vector: Vector3, planeNormal: Vector3)
	local projectedVector = projectOnPlane(vector, planeNormal).Unit
	return projectedVector * vector.Magnitude
end

local colliderRadius = 1
local wallOffset = 0.015

local function collideAndSlide(position: Vector3, velocity: Vector3, depth: number): Vector3
	if depth > 3 then return Vector3.zero end
	
	local direction = velocity.Unit * (velocity.Magnitude + wallOffset)
	local hitResult = workspace:Spherecast(position, colliderRadius, velocity)
	
	if hitResult then
		local snapToSurface = velocity.Unit * (hitResult.Distance - wallOffset)
		local leftover = velocity - snapToSurface
		
		if snapToSurface.Magnitude <= wallOffset then
			snapToSurface = Vector3.zero
		end

		leftover = projectAndScale(leftover, hitResult.Normal)
		return snapToSurface + collideAndSlide(position + snapToSurface, leftover, depth+1)
	end
	
	return velocity
end

Increasing the wallOffset to something like 0.25 make it harder to go through walls, but you still end up going through walls if you try hard enough with different camera angles.
This problem is driving me nuts, any help is really appreciated.

1 Like