WalkSpeed changed not working on ServerScript

Hello! I’m having an issue with a server script. For some reason, the humanoid:GetPropertyChangedSignal isn’t firing.

The code is written below:


-- // Services
local replicatedStorage = game:GetService("ReplicatedStorage")
local playersService = game:GetService("Players")
local debris = game:GetService("Debris")

-- // Variables
local footstepsModule = require(replicatedStorage.Modules:WaitForChild("FootstepsModule"))

-- // Functions
local function checkSpeed(humanoid)
	
	local walkSpeed = humanoid.WalkSpeed
	local moveDirection = humanoid.MoveDirection.Magnitude
	local floorMaterial = humanoid.FloorMaterial
	
	if walkSpeed > 0 and moveDirection > 0 and floorMaterial ~= Enum.Material.Air then
		return true
	end
	
	return false
end

local function getMaterial(material)
	local soundTable = footstepsModule:GetTableFromMaterial(material)
	
	if soundTable then
		local randomSound = footstepsModule:GetRandomSound(soundTable)
		
		if randomSound then
			return randomSound
		end
	end
	
	return nil
end

local function shootRay(rayOrigin, rayDirection, raycastParams)
	
	local raycastResult = workspace:Raycast(rayOrigin, rayDirection, raycastParams)
	
	if raycastResult then
		return raycastResult.Material
	end
	
	return nil
end

local function createFootstep(sound, character, rootPart)
	
	local rayOrigin = rootPart.Position
	local rayDirection = Vector3.new(0, -5, 0)
	
	local raycastParams = RaycastParams.new()
	raycastParams.FilterType = Enum.RaycastFilterType.Exclude
	raycastParams.IgnoreWater = false
	raycastParams.FilterDescendantsInstances = {character}
	
	local raycastResult = shootRay(rayOrigin, rayDirection, raycastParams)
	
	if raycastResult ~= nil then
		local newSound = getMaterial(raycastResult)
		sound.SoundId = newSound
		
		local newFootstep = sound:Clone()
		newFootstep.Name = "Footstep"
		newFootstep.PlaybackSpeed = math.random(9, 11) / 10
		
		newFootstep.Parent = rootPart
		
		newFootstep:Play()
		debris:AddItem(newFootstep, 2)
	end
	
end

-- // Events
playersService.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		
		local humanoid = character:WaitForChild("Humanoid")
		local rootPart = character:WaitForChild("HumanoidRootPart")
		
		-- Sound creation
		local footstepsSound = Instance.new("Sound")
		footstepsSound.Name = "FootstepTemplate"
		footstepsSound.Volume = 0.5
		
		footstepsSound.RollOffMode = Enum.RollOffMode.InverseTapered
		footstepsSound.RollOffMaxDistance = 35
		footstepsSound.RollOffMinDistance = 15
		
		
		footstepsSound.Parent = rootPart
		
		local cooldown = 0.4
		
		
		local function onWalkSpeedChanged(speed)
			print("WalkSpeed changed")
		end
		
		humanoid:GetPropertyChangedSignal("WalkSpeed"):Connect(onWalkSpeedChanged)

		
		
		-- Main loop
		while humanoid.Health > 0 do
			task.wait(cooldown)
			if checkSpeed(humanoid) then
				createFootstep(footstepsSound, character, rootPart)
				
				print("Script is working")
			end
		end
		
	end)
end)

“Script is working” is getting printed, but “Walkspeed changed” is not. Help would be appeciated!

4 Likes

The only reason i see this happening is when the humanoid isn’t detected anymore.

3 Likes

Try using an anonymous function and see if that changes anything.

humanoid:GetPropertyChangedSignal("WalkSpeed"):Connect(function()
  print("WalkSpeed changed!")
end)

If not, try throwing out the while do loop. It could be preventing the event from firing, but since it’s hooked before the loop commences, there shouldn’t be an issue.

2 Likes

Hey; the humanoid is still being detected (at least to my knowledge) as when I throw a print(humanoid.Parent.Name) into the loop, it continuously prints the Player Character’s name.

2 Likes

Tried the anonymous function as shown below:

playersService.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		
		local humanoid = character:WaitForChild("Humanoid")
		local rootPart = character:WaitForChild("HumanoidRootPart")
		
		-- Sound creation
		local footstepsSound = Instance.new("Sound")
		footstepsSound.Name = "FootstepTemplate"
		footstepsSound.Volume = 0.5
		
		footstepsSound.RollOffMode = Enum.RollOffMode.InverseTapered
		footstepsSound.RollOffMaxDistance = 35
		footstepsSound.RollOffMinDistance = 15
		
		
		footstepsSound.Parent = rootPart
		
		local cooldown = 0.4
		
		
		humanoid:GetPropertyChangedSignal("WalkSpeed"):Connect(function()
			print("WalkSpeed changed!")
		end)


		
		-- Main loop
		while humanoid.Health > 0 do
			task.wait(cooldown)
			if checkSpeed(humanoid) then
				createFootstep(footstepsSound, character, rootPart)

				print("Script is working")
			end
		end
		
	end)
end)

Same result as earlier. Could it really be the loop? I’ve tested moving the function in and out of the loop and the issue persists.

1 Like

Try wrapping the loop in a coroutine or a task.spawn() call.

1 Like

does the loop print when your character dies?

My first time using task.spawn() :sweat_smile:
Hope I used it right!

-- // Events
playersService.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)

		local humanoid = character:WaitForChild("Humanoid")
		local rootPart = character:WaitForChild("HumanoidRootPart")

		-- Sound creation
		local footstepsSound = Instance.new("Sound")
		footstepsSound.Name = "FootstepTemplate"
		footstepsSound.Volume = 0.5

		footstepsSound.RollOffMode = Enum.RollOffMode.InverseTapered
		footstepsSound.RollOffMaxDistance = 35
		footstepsSound.RollOffMinDistance = 15


		footstepsSound.Parent = rootPart

		local cooldown = 0.4


		humanoid:GetPropertyChangedSignal("WalkSpeed"):Connect(function()
			print("WalkSpeed changed!")
		end)



		-- Main loop
		task.spawn(function()
			while humanoid.Health > 0 do
				task.wait(cooldown)
				if checkSpeed(humanoid) then
					createFootstep(footstepsSound, character, rootPart)

					print("Script is working")
				end
			end
		end)

	end)
end)

Unfortunately, it doesn’t seem to fix the problem and “WalkSpeed changed” is still not getting printed. I have also tried a coroutine.

That is proper usage.

Add a task.wait() before the while loop and see if that fixes things?

When I attempt to move after I died, nothing gets printed until I respawn. After my character gets respawned, it continues as normal in printing “Script is working” and my character name.

Tried the following:

playersService.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)

		local humanoid = character:WaitForChild("Humanoid")
		local rootPart = character:WaitForChild("HumanoidRootPart")

		-- Sound creation
		local footstepsSound = Instance.new("Sound")
		footstepsSound.Name = "FootstepTemplate"
		footstepsSound.Volume = 0.5

		footstepsSound.RollOffMode = Enum.RollOffMode.InverseTapered
		footstepsSound.RollOffMaxDistance = 35
		footstepsSound.RollOffMinDistance = 15


		footstepsSound.Parent = rootPart

		local cooldown = 0.4


		humanoid:GetPropertyChangedSignal("WalkSpeed"):Connect(function()
			print("WalkSpeed changed!")
		end)


		task.wait()
		-- Main loop
		task.spawn(function()
			while humanoid.Health > 0 do
				task.wait(cooldown)
				if checkSpeed(humanoid) then
					createFootstep(footstepsSound, character, rootPart)

					print("Script is working")
				end
			end
		end)

	end)
end)

Still no solution. Any other ideas?

Note: I have also tired putting task.wait() within the task.spawn() as shown below, but to no avail.

task.spawn(function()
        task.wait()
	while humanoid.Health > 0 do
		task.wait(cooldown)
		if checkSpeed(humanoid) then
			createFootstep(footstepsSound, character, rootPart)

			print("Script is working")
			print(humanoid.Parent.Name)
		end
	end
end)

There’s no need for the task.spawn or the task.wait. You can remove both, it won’t change anything.

I see nothing wrong with your code. The only thing I may presume is happening is that the code you showed us is written on a server script, but you are changing the Humanoid’s WalkSpeed on the client somewhere else. Is this the case?

Hello, I’ve been reading your post and the issue might be related to the humanoid being nil. I recommend printing the humanoid variable to verify its being correctly stored.

If this is true, I recommend you implement the following code in the characteradded section:

repeat task.wait() until character.Humanoid ~= nil

This code repeats the code task.wait() intil roblox has successfully loaded the humanoid.

He’s using :WaitForChild() anyways. There isn’t much point on that repeat loop.

Sometimes there are uses like the character model itself being nil or waitforchild not working for some reason

1 Like

I am changing the Walkspeed on the client via a client script that acts as a “Sprint” script. It simply sets the speed like below:

Humanoid.WalkSpeed = 25

Could this be the issue? Server isn’t detecting Walkspeed changes made by the client?

Doesn’t seem to be the issue. I setup the print statement within the loop so it constantly prints the Humanoid instance, and it never prints nil or anything related to it not existing.

Correct!
See, every single Client is connected to the server. If something changes on the Server, all Clients see the change as well! However, if a Client makes a change, only they can see it, meaning the Server or any other Client in the game cannot read the change.

Now, if you want this to work, you should have the WalkSpeed be changed on the Server. You can typically use a RemoteEvent for this.

2 Likes

I’m not sure if you are doing this but make sure to print the variable, not Character.Humanoid. This is because the valur of Character.Humanoid can start off as nil but later become loaded in

They are detecting walking. This is allowable on the server.