How to tell if a player has truly stopped moving, not strafing?

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!
    I want to check if player has moved in the past decisecond (0.1 seconds) or so to prevent the animation from resetting but in this case, I need to find if the player has TRULY stopped moving (not strafing, spamming movement keys, etc.)

  2. What is the issue? Include screenshots / videos if possible!
    Two code examples are functioning differently when they should theoretically be functioning the same, and how can I make it more efficient?

  3. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    Tried experimenting with time() and found somebody else’s code (I don’t remember where I found it and modified it a bit but it now doesn’t work.

CODE EXAMPLE 1: THE ONE THAT WORKS

runService.Heartbeat:Connect(function(step)
    if humanoid.MoveDirection.Magnitude == 0 then
        local newTime = 0
        while (newTime < .1) do
            if humanoid.MoveDirection.Magnitude ~= 0 then return end
            newTime += runService.Heartbeat:Wait()
        end
        print("not moving")
    end
end)

CODE EXAMPLE 2: THE ONE THAT DOES NOT WORK

runService.Heartbeat:Connect(function(step)
    local moveDirection = humanoid.MoveDirection
    if moveDirection.Magnitude == 0 then
        local newTime = 0
        while (newTime < .1) do
            if moveDirection.Magnitude ~= 0 then return end
            newTime += runService.Heartbeat:Wait()
        end
        print("not moving")
    end
end)

Check the Velocity of the HumanoidRootPart.

2 Likes

You need to identify if the CFrame of the HumanoidRootPart has not changed at all from the previous frame.

1 Like

Like what @DasKairo said:

if character.HumanoidRootPart.Velocity.Magnitude < 0.1 then -- it's 0.1 because for some reason it's not always 0
        -- Do what u want or something
end
2 Likes

Just some Slight Improvement:

if HumanoidRootPart.AssemblyLinearVelocity.Magnitude < .001 then -- the .001 is to ensure they arent moving
-- code
end
2 Likes

Here’s something that detects if the player is moving based on CFrame.

local lastCF = CFrame.new()
--Assign the 'char' variable to the player's character
--From there, assign the 'part' variable to the player's HumanoidRootPart
runService.Heartbeat:Connect(function(step)
    newCF = part.CFrame
    if lastCF.Position:FuzzyEq(newCF.Position) then
        --The player has essentially stopped moving
        --but are they strafing?
        if lastCF.LookVector:FuzzyEq(newCF.LookVector) then
            --The player is not moving or strafing
            --(do stuff here)
        end
    end
    lastCF = newCF
end)
2 Likes

runService.Heartbeat:Connect(function(step)
	local newCF = root_part.CFrame
	if lastCF.Position:FuzzyEq(newCF.Position) then
		--The player has essentially stopped moving
		--but are they strafing?
		if lastCF.LookVector:FuzzyEq(newCF.LookVector) then
			--The player is not moving or strafing
			--(do stuff here)
			print("not moving")
		end
	end
	lastCF = newCF
end)

This prints regardless regardless if I am moving or not for some reason.

This works but it’s less accurate than the first example, I have tried this before.

Edit: Thank you everyone for answering, it means a lot. Also, I found that the original script I provided seems rather “fragile”, like hanging-on-a-thread type of fragile. I have scrapped the original script for now as it isn’t very safe/stable in my opinion.

I must have forgotten to correctly specify the 2nd argument (FuzzyEq) to the script. I have updated the code:

local lastCF = CFrame.new()
runService.Heartbeat:Connect(function(step)
	local newCF = root_part.CFrame
	if lastCF.Position:FuzzyEq(newCF.Position, .0001) then
		--The player has essentially stopped moving
		--but are they strafing?
		if lastCF.LookVector:FuzzyEq(newCF.LookVector, .0001) then
			--The player is not moving or strafing
			--(do stuff here)
			print("not moving")
		end
	end
	lastCF = newCF
end)

It should print “not moving” if the player is not moving or strafing, whereas the other examples do not account for strafing as movement.

1 Like

Thanks a lot for answering unfortunately the same issue is still here.

Hm. Try decreasing the decimal values in both fields. I haven’t tested this with R6 rigs.

1 Like

Each heartbeat, take the position of the HumanoidRootPart, then do a magnitude check on the previous and current position. If it’s below a threshold (you can check by printing the difference) you can easily determine if they have moved or not.

1 Like

Then that would be affected by other things too, no? Like, something pushing me for example.

Still not working, thanks for replying anyway. Edit, I have a few ideas, namely a “stride wheel” like the one in this video at the time stamp of 5:25.

local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local Character = Player.Character

-- Wait for the character to be fully loaded
Character:WaitForChild("Humanoid")

-- Get the character's humanoid object
local Humanoid = Character:FindFirstChildOfClass("Humanoid")
local isMoving = false

Humanoid.Changed:Connect(function(property)
	if property == "MoveDirection" then
		if Humanoid.MoveDirection == Vector3.new(0,0,0) then
			if isMoving then
				-- The character has stopped moving
				print("Character stopped moving")
			end

			isMoving = false
		else
			if not isMoving then
				-- The character has started moving
				print("Character started moving")
			end

			isMoving = true
		end
	end
end)
1 Like

@Moodmonger Humanoid State Changed has a feature that lets you see if a humanoid is jumping, running, strafing, etc.

1 `Humanoid.StateChanged:Connect(function(old , new)
2	    if new == Enum.HumanoidStateType.Running then
3	        --Player is running
4	    elseif new == Enum.HumanoidStateType.Jumping then
5	        --Player has jumped
6	    end
7	end)
`

What do the old and new params mean?

Well the old param is your old state before the new one I believe. But you don’t have to mess with it.

You can also use ~= instead of == to see if it is not moving