Some movement bugs using assemblyLinearVelocity

So I want to make a movement system which i have total control over using assemblyLinearVelocity for the HumanoidRootPart.
I want to make it as accurate as possible to the normal movement, except for climbing and adding spinting, sliding etc.
There are 4 problems to be exact

  • Falling down near a platform causes the HumanoidRootPart to get stuck for a bit (kinda solved)
  • The same thing for jumping up and getting stuck between the gap of 2 parts on top of each other
  • when im walking against the wall, the character is shaking a bit
  • Climbing up the stairs sideways, causes the HumanoidRootPart to hit the elevated part

This is the part of the script that runs on every frame that controls the jump and move function in the PlayerModule with RenderStepped()


function ControlModule:JumpHandler(Jump: boolean, dt)
	if not self.humanoid or self.humanoid.Health <= 0 then return end
	local HumanoidRootPart = self.humanoid.RootPart
	local currentVel = HumanoidRootPart.AssemblyLinearVelocity

	local isGrounded = false
	
	if self.humanoid.FloorMaterial ~= Enum.Material.Air and self:CheckGrounded() then
		
		isGrounded = true
		
	end

	if isGrounded and self.VerticalVelocity <= 0 then		
		self.JumpEnabled = true
		self.VerticalVelocity = 0 
		self.WallKickAmount = 0 
	else		
		self.JumpEnabled = false
		
		if self.VerticalVelocity > 0 then -- If head hit a roof
		
			local HitHead = false
			
			local corners = getTopCorners(HumanoidRootPart)
			
			local rayCastDir = Vector3.new(0, 10, 0)
			local rayCastParams = RaycastParams.new()
			rayCastParams.FilterDescendantsInstances = {HumanoidRootPart.Parent}
			rayCastParams.FilterType = Enum.RaycastFilterType.Exclude

			local raycastResults = {}
			raycastResults[1] = workspace:Raycast(corners.TopFrontRight, rayCastDir, rayCastParams)
			raycastResults[2] = workspace:Raycast(corners.TopFrontLeft, rayCastDir, rayCastParams)
			raycastResults[3] = workspace:Raycast(corners.TopBackRight, rayCastDir, rayCastParams)
			raycastResults[4] = workspace:Raycast(corners.TopBackLeft, rayCastDir, rayCastParams)
			
			for i = 1, 4 do
				if raycastResults[i] ~= nil and raycastResults[i].Distance < 1.1 then
					HitHead	= true
				end
			end
			
			if HitHead then
				self.VerticalVelocity = self.VerticalVelocity * -1 
			end
		end
		
		local gravityToApply = 200

		self.VerticalVelocity -= gravityToApply * dt
		--Velocity cap
		if self.VerticalVelocity < -150 then
			self.VerticalVelocity = -150
		end
	end
	-- Jump
	if self.activeController:GetIsJumping() and self.JumpEnabled then
	
		self.JumpEnabled = false
		
		local power = (self.humanoid.JumpPower > 0) and self.humanoid.JumpPower or 50
		
		self.humanoid:ChangeState(Enum.HumanoidStateType.Jumping) 
		
		self.VerticalVelocity = power
	end

	local finalY = self.VerticalVelocity
		
	HumanoidRootPart.AssemblyLinearVelocity = Vector3.new(currentVel.X, finalY, currentVel.Z)
end

function ControlModule:Move(direction: Vector3, relativeToCam: boolean, dt)

	if not self.humanoid or self.humanoid.Health <= 0 then return end

	local HumanoidRootPart : Part = self.humanoid.RootPart

	if relativeToCam then

		if direction.Magnitude > 0 then

		HumanoidRootPart.AssemblyLinearVelocity = direction.Unit * self.humanoid.WalkSpeed

		local targetLook = HumanoidRootPart.Position + Vector3.new(direction.X, 0, direction.Z)

				-- 2. Create the target CFrame
		local targetCFrame = CFrame.lookAt(HumanoidRootPart.Position, targetLook)



		HumanoidRootPart.CFrame = HumanoidRootPart.CFrame:Lerp(targetCFrame, dt * 10)
	

	else

		HumanoidRootPart.AssemblyLinearVelocity = Vector3.new(0,0,0)

	end
		
end



1 Like

You need to set the humanoidrootpart custom physical properties to

100 Friction Weight 100 Elastic Weight and everything off

1 Like

I changed the custom physical properties to the same setting as you suggested.
It helped a bit with the problem, where fallling down near a platform causes the HumanoidRootPart to be stuck.

Thank you for the help!

Sweet! You can also use a capsule collider or sphere instead of a block to allow smooth contact.

2 Likes

The core issue here is that AssemblyLinearVelocity alone doesn’t handle collision response — you’re manually setting velocity but the physics engine still needs to resolve contacts naturally. This creates the stuttering and sticking you’re experiencing.Here’s what’s happening:**Problem 1 & 2 (Falling/Jumping Sticking):**You’re likely overriding velocity every frame without accounting for collision impulses. When the character lands or hits a wall, Roblox applies corrective forces, but you’re immediately resetting them. Use AssemblyLinearVelocity for horizontal movement only, and let gravity handle the Y-axis naturally:lualocal moveDirection = getYourInputDirection() * moveSpeedlocal currentVel = HumanoidRootPart.AssemblyLinearVelocityHumanoidRootPart.AssemblyLinearVelocity = Vector3.new( moveDirection.X, currentVel.Y, -- Preserve gravity moveDirection.Z)**Problem 3 (Shaking):**This is typically caused by setting velocity every frame without smoothing. Add lerping:lualocal targetVel = Vector3.new(moveDirection.X, currentVel.Y, moveDirection.Z)HumanoidRootPart.AssemblyLinearVelocity = currentVel:Lerp(targetVel, 0.15)**Problem 4 (Stair Collision):**Climbing stairs sideways fails because you’re not checking for ground contact. Implement raycasting or use Humanoid:GetState() to verify grounding:luaif Humanoid:GetState() == Enum.HumanoidStateType.Landed or isGrounded then -- Apply horizontal velocityendKey recommendation: Consider keeping the default Humanoid movement for ground locomotion and only use AssemblyLinearVelocity for air control, sprinting, and sliding. This hybrid approach gives you the precision you want without fighting Roblox’s collision system.