Custom character's collision does not work

  1. What do you want to achieve?
    I’m trying to create a custom character controller without using vector forces or Roblox’s physics. My character controller uses math to calculate the character’s position. I used this video to help me implement collision detection.
  1. What is the issue?
    The issue is that the collision detection is very buggy. You can go through walls and the floor. Whenever you move on the ground, you just clip into the floor. You can stand on the ground though.

robloxapp-20240317-1401039.wmv (1.6 MB)

  1. What solutions have you tried so far?
    I looked all over the devforum but haven’t found anything. I tried looking into chickynoid’s code, but couldn’t understand anything.
local Velocity = Vector3.new()
	
local Gravity = Vector3.new(0, -1 * Delta, 0)

if Jump then
	Gravity = Vector3.new(0, 16 * Delta, 0)
end
	
--The problem lies somewhere here
local MoveAmount = MovementSystem.CollideAndSlide(Character, PlayerMovementParams, Total, false, ReplicationRaycastParams)
MoveAmount += MovementSystem.CollideAndSlide(Character, PlayerMovementParams, Gravity, true, ReplicationRaycastParams)
--

Character.Position += MoveAmount
--MovementSystem Module
local function dot(vec, other)
	return vec:Dot(other)
end

local function projectOnPlane(v,n)	
	return v - (((v:Dot(n))/(n.Magnitude)^2)*n)
end

local function projectAndScale(vec: Vector3, normal: Vector3)
	return projectOnPlane(vec, normal).Unit * vec.Magnitude
end


local function isGrounded(char: BasePart, params: RaycastParams)
	local Origin = char.Position
	local Direction = Vector3.new(0, (char.Size.Y/-2) -0.725, 0)
	local GroundRaycast = workspace:Raycast(Origin, Direction, params)
	
	if GroundRaycast then
		 return true
	end
	
	return false
end

local function collideAndSlide(char: BasePart, collisionParams: RaycastParams, moveParams, vel: Vector3, pos: Vector3, depth: number, gravityPass: boolean, isGrounded: boolean, velInit: Vector3)
	if depth >= 5.0 then
		return Vector3.zero
	end
	
	local skinWidth = 0.015
	
	local dist = vel.Magnitude + skinWidth
	dist = math.clamp(dist, -1000, 1000)
	
	if dist ~= dist then
		dist = skinWidth
	end
	
	local size = char.Size - (char.Size.Unit * skinWidth * 2)
	local dir = vel.Unit * dist
	
	if dir ~= dir then
		dir = Vector3.zero
	end
	
	local hit = workspace:Blockcast(CFrame.new(pos, dir), char.Size, dir, collisionParams)
	--hitbox.Size = size
	--hitbox.Position = pos
	
	if hit then
		--isHit.Position = hit.Position
	else
		--isHit.Position = pos + dir
	end
	
	if hit then
		local snapToSurface = vel.Unit * (hit.Distance - skinWidth)
		local leftOver = vel - snapToSurface
		local angle = Vector3.yAxis:Angle(hit.Normal)
		
		if snapToSurface.Magnitude <= skinWidth then
			snapToSurface = Vector3.zero
		end
		
		if angle <= moveParams.MaxSlopeAngle then
			--Normal Ground
			if gravityPass then
				return snapToSurface
			end
			
			leftOver = projectAndScale(leftOver, hit.Normal)
		else
			--Slope
			local scale = 1 - dot(
				Vector3.new(hit.Normal.X, 0, hit.Normal.Z).Unit,
				-Vector3.new(velInit.X, 0, velInit.Z).Unit
			)
			
			if isGrounded and gravityPass then
				leftOver = projectAndScale(
					Vector3.new(leftOver.X, 0, leftOver.Z),
					Vector3.new(hit.Normal.X, 0, hit.Normal.Z)
				).Unit
				
				leftOver *= Vector3.new(scale, 0, scale)
			else
				leftOver = projectAndScale(leftOver, hit.Normal) * scale
			end
		end
		
		if leftOver ~= leftOver then
			leftOver = Vector3.one*skinWidth
		end
		
		return snapToSurface + collideAndSlide(char, collisionParams, moveParams, leftOver, pos + snapToSurface, depth + 1, gravityPass, isGrounded, velInit)
	end
	
	if vel ~= vel then
		vel = Vector3.zero
	end
	
	return vel
end

local MovementSystem = {}

function MovementSystem.CollideAndSlide(Character: BasePart, MovementParams: MovementParams, TotalVelocity: Vector3, GravityPass: boolean, CollisionParams: RaycastParams)
	local IsGrounded = isGrounded(Character, CollisionParams)
	local Velocity = TotalVelocity
	
	if TotalVelocity ~= TotalVelocity then
		Velocity = Vector3.zero
	end
	
	return collideAndSlide(Character, CollisionParams, MovementParams, TotalVelocity, Character.Position, 0, GravityPass, IsGrounded, TotalVelocity)
end

Sorry I do not have a definite answer, but I think that Chickynoid has it’s own physics simulation including collision, perhaps you can check that out :slight_smile:

hi ! send over the rbxl file ill see what i can do.

CustomCharacterController.rbxl (88.0 KB)