How can I add working collisions to a custom character controller?

im currently working on a custom character controller for npcs in my game as im planning on storing their position on the server inside of a script and rendering them on the client as large quantities of humanoids (which are needed for my game) walk extremely slowly

the problem with this is that i have to make a custom script to handle physics, which i dont know how to do correctly, resulting in the character uncontrollably bouncing after landing as well as phasing straight through walls

examples:


current code that im using:

function AIHandler.new(Data)
	local self = setmetatable({}, AIHandler)
	
	self.WalkSpeed = Data.WalkSpeed
	
	self.Part = Data.Part
	self.CFrame = Data.Part.CFrame
	
	self.Acceleration = Vector3.new(0, 0, 0)
	
	self.IsMoving = false
	
	self.MoveFunction = nil
	
	local PhysicsRaycastParams = RaycastParams.new()
	PhysicsRaycastParams.FilterType = Enum.RaycastFilterType.Exclude
	PhysicsRaycastParams.FilterDescendantsInstances = {self.Part}
	
	self.PhysicsUpdater = RunService.Stepped:Connect(function(Time, DeltaTime)
		local GravityToApply = Vector3.new(0, workspace.Gravity * DeltaTime, 0)
		
		local DoesFloorExist = workspace:Raycast(self.CFrame.Position, Vector3.new(0, -1, 0) * 2.6, PhysicsRaycastParams)
		
		if not DoesFloorExist then
			if (self.Acceleration - GravityToApply).Y > -workspace.Gravity then
				self.Acceleration -= GravityToApply
			end
		else
			self.Acceleration = Vector3.new(0, 0, 0)
		end
	end)
	
	return self
end

function AIHandler:MoveTo(CFrame)
	self.IsMoving = true
	
	self.MoveFunction = RunService.Stepped:Connect(function(Time, DeltaTime)
		if (self.CFrame.Position - CFrame.Position).Magnitude > 1 then
			self.CFrame += (CFrame.Position - self.CFrame.Position).Unit * (self.WalkSpeed * DeltaTime)
			self.CFrame += self.Acceleration * DeltaTime
		else
			self.IsMoving = false
			
			self.MoveFunction:Disconnect()
		end
	end)
end

function AIHandler:Jump()
	self.Acceleration += Vector3.new(0, 50, 0)
end
``
2 Likes

bump, im looking for a solution on this too lol

You can use raycasting to do collisions.

Just raycast down to get the floor, if there is a floor move the character up, and if there isn’t a floor, accelerate the character downwards. (You can also add a second raycast downwards starting from slightly in front of the other raycast to do stairs and stuff a little better).

Then for forward collisions just use a raycast (or a few) going forwards and if they hit anything stop the character.

Thats what im doing and it’s the cause of the bouncing problem

Is your code moving the character to exactly the surface hit height plus their hip height? If the code just moves them up not exactly the right amount then they’ve go from moving up to down.

Another problem might be that the character is just falling and needs to be anchored (or held in place with an AlignPosition and AlignOrientation).