Issue with Sound.Playing randomly toggling into a false state

I’m working on a footstep system. All is going rather well except for a rather major issue where the Sound.Playing state for my footsteps is seemingly randomly set to false. The only way to undo this in playtesting mode is to jump.

Here’s the server script that handles the majority of the footsteps.

local players = game:GetService("Players")
local running = game.ReplicatedStorage:WaitForChild("running")
local notrunning = game.ReplicatedStorage:WaitForChild("notrunning")
local footstepsModule = require(game.ReplicatedStorage:WaitForChild("FootstepModule"))
local runservice = game:GetService("RunService")
cooldown = .38

local function footstepsplayingdetect(footsteps)
	runservice.Heartbeat:Connect(function()
		return footsteps.Playing  ~= true and footsteps.Playing == false
	end)
end

local function footstepsplayingfix(footsteps)
	if footstepsplayingdetect(footsteps) then
		footsteps.Playing = true
	end
end

local function check_movement(humanoid)
	return humanoid.WalkSpeed > 0 and humanoid.MoveDirection.Magnitude > 0 and humanoid.FloorMaterial ~= Enum.Material.Air 
end

local function isrunning(running, notrunning)
	notrunning.OnServerEvent:Connect(function()
		cooldown = .38
	end)
	running.OnServerEvent:Connect(function()
		cooldown = .28
	end)
end

local function get_material(floorMaterial)
	local SoundTable = footstepsModule:GetTableFromMaterial(floorMaterial)
	return footstepsModule:GetRandomSound(SoundTable)
end

local function runningmovement(humanoid, footsteps)
	if check_movement(humanoid) then
		isrunning(running, notrunning)
		footstepsplayingfix(footsteps)
		local soundId = get_material(humanoid.FloorMaterial)

		footsteps.SoundId = soundId
		footsteps:Play()
		wait(cooldown)
	else
		repeat
			wait()
		until
		check_movement(humanoid)
		return
	end
end

players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		local humanoid = character:WaitForChild("Humanoid")
		local root = character:WaitForChild("HumanoidRootPart")

		local footsteps = Instance.new("Sound")
		footsteps.Name = "footstepssound"
		footsteps.Volume = 0.8
		footsteps.RollOffMaxDistance = 40
		footsteps.RollOffMinDistance = 2
		footsteps.RollOffMode = Enum.RollOffMode.Linear
		footsteps.Parent = root
		
		while true do
			runningmovement(humanoid, footsteps)
		end
	end)
end)

Every player gets a footstep, placed inside the HumanoidRootPart. It picks from a list of materials, based on what the player is standing on, and if the player is moving, plays the sound. Once the sound is finished, it gets and plays another, so on and so forth.
I’ve tried remedying the situation myself, seen in footstepsplayingdetect() and footstepsplayingfix() however they either don’t work at all or don’t work very well.

Some other scripts too, if you think you need to look at them.

ModuleScript

I have checked alot (not all of them) of the Id’s in this list, which wasn’t made by me, to see if they’re either broken or privated and to my knowledge they are neither and I do not believe the problem lies in the ModuleScript.

-- this was made by uglyburger0, all credits to them. none to me
local main = {}

main.SoundIds = {
	["Bass"] = {
		"rbxassetid://9126748907",
		"rbxassetid://9126748813",
		"rbxassetid://9126748580",
		"rbxassetid://9126748691",
		"rbxassetid://9126748431",
		"rbxassetid://9126748324",
		"rbxassetid://9126748239",
		"rbxassetid://9126748185",
		"rbxassetid://9126748045",
		"rbxassetid://9126747958"
	},
	
	["Carpet"] = {
		"rbxassetid://9126748130",
		"rbxassetid://9126747861",
		"rbxassetid://9126747720",
		"rbxassetid://9126747529",
		"rbxassetid://9126747412",
		"rbxassetid://9126747283",
		"rbxassetid://9126746732",
		"rbxassetid://9126746837",
		"rbxassetid://9126747132",
		"rbxassetid://9126746984",
		"rbxassetid://9126746598",
		"rbxassetid://9126746481",
		"rbxassetid://9126746371",
		"rbxassetid://9126746291"
	},
	
	["Concrete"] = {
		"rbxassetid://9126746167",
		"rbxassetid://9126746098",
		"rbxassetid://9126745995",
		"rbxassetid://9126745877",
		"rbxassetid://9126745774",
		"rbxassetid://9126745574",
		"rbxassetid://9126745336",
		"rbxassetid://9126745241",
		"rbxassetid://9126745445",
		"rbxassetid://9126745052",
		"rbxassetid://9126745141",
		"rbxassetid://9126745676",
		"rbxassetid://9126744969",
		"rbxassetid://9126744894",
		"rbxassetid://9126744639",
		"rbxassetid://9126744789",
		"rbxassetid://9126744481"
	},
	
	["Dirt"] = {
		"rbxassetid://9126744390",
		"rbxassetid://9126744718",
		"rbxassetid://9126744263",
		"rbxassetid://9126744157",
		"rbxassetid://9126744066",
		"rbxassetid://9126744009",
		"rbxassetid://9126743796",
		"rbxassetid://9126743938",
		"rbxassetid://9126743711",
		"rbxassetid://9126743879",
		"rbxassetid://9126743613",
		"rbxassetid://9126743481",
		"rbxassetid://9126743338",
		"rbxassetid://9126743086"
	},
	
	["Glass"] = {
		"rbxassetid://9126742971",
		"rbxassetid://9126742461",
		"rbxassetid://9126742875",
		"rbxassetid://9126742786",
		"rbxassetid://9126743193",
		"rbxassetid://9126742680",
		"rbxassetid://9126742582",
		"rbxassetid://9126742510"
	},
	
	["Grass"] = {
		"rbxassetid://9126742396",
		"rbxassetid://9126741427",
		"rbxassetid://9126742333",
		"rbxassetid://9126742215",
		"rbxassetid://9126742271",
		"rbxassetid://9126742031",
		"rbxassetid://9126741934",
		"rbxassetid://9126742105",
		"rbxassetid://9126741826",
		"rbxassetid://9126741594",
		"rbxassetid://9126741512",
		"rbxassetid://9126741741",
		"rbxassetid://9126741674"
	},
	
	["Gravel"] = {
		"rbxassetid://9126741273",
		"rbxassetid://9126740393",
		"rbxassetid://9126741200",
		"rbxassetid://9126741051",
		"rbxassetid://9126741128",
		"rbxassetid://9126740951",
		"rbxassetid://9126740802",
		"rbxassetid://9126740724",
		"rbxassetid://9126740524",
		"rbxassetid://9126740623"
	},
	
	["Ladder"] = {
		"rbxassetid://9126740217",
		"rbxassetid://9126739039",
		"rbxassetid://9126740133",
		"rbxassetid://9126739947",
		"rbxassetid://9126740044",
		"rbxassetid://9126740305",
		"rbxassetid://9126739834",
		"rbxassetid://9126739622",
		"rbxassetid://9126739505",
		"rbxassetid://9126739406",
		"rbxassetid://9126739332",
		"rbxassetid://9126739229"
	},
	
	["Metal_Auto"] = {
		"rbxassetid://9126739090",
		"rbxassetid://9126738967",
		"rbxassetid://9126738896",
		"rbxassetid://9126738732",
		"rbxassetid://9126738543",
		"rbxassetid://9126738634"
	},
	
	["Metal_Chainlink"] = {
		"rbxassetid://9126738423",
		"rbxassetid://9126737791",
		"rbxassetid://9126738338",
		"rbxassetid://9126738197",
		"rbxassetid://9126738113",
		"rbxassetid://9126738032",
		"rbxassetid://9126737943",
		"rbxassetid://9126737853"
	},
	
	["Metal_Grate"] = {
		"rbxassetid://9126737728",
		"rbxassetid://9126736554",
		"rbxassetid://9126737597",
		"rbxassetid://9126737668",
		"rbxassetid://9126737506",
		"rbxassetid://9126737412",
		"rbxassetid://9126737315",
		"rbxassetid://9126737212",
		"rbxassetid://9126736947",
		"rbxassetid://9126737081",
		"rbxassetid://9126736863",
		"rbxassetid://9126736806",
		"rbxassetid://9126736642",
		"rbxassetid://9126736721"
	},
	
	["Metal_Solid"] = {
		"rbxassetid://9126736470",
		"rbxassetid://9126734921",
		"rbxassetid://9126736274",
		"rbxassetid://9126736354",
		"rbxassetid://9126736186",
		"rbxassetid://9126736049",
		"rbxassetid://9126735913",
		"rbxassetid://9126735734",
		"rbxassetid://9126735546",
		"rbxassetid://9126735474",
		"rbxassetid://9126735265",
		"rbxassetid://9126735374",
		"rbxassetid://9126735161",
		"rbxassetid://9126735028",
		"rbxassetid://9126735089",
		"rbxassetid://9126734972"
	},
	
	["Mud"] = {
		"rbxassetid://9126734842",
		"rbxassetid://9126734314",
		"rbxassetid://9126734778",
		"rbxassetid://9126734710",
		"rbxassetid://9126734613",
		"rbxassetid://9126734499",
		"rbxassetid://9126734365",
		"rbxassetid://9126734432",
		"rbxassetid://9126734244"
	},
	
	["Rubber"] = {
		"rbxassetid://9126734172",
		"rbxassetid://9126733896",
		"rbxassetid://9126734560",
		"rbxassetid://9126734010",
		"rbxassetid://9126733324",
		"rbxassetid://9126733766",
		"rbxassetid://9126733614",
		"rbxassetid://9126733493"
	},
	
	["Sand"] = {
		"rbxassetid://9126733118",
		"rbxassetid://9126733408",
		"rbxassetid://9126733225",
		"rbxassetid://9126732675",
		"rbxassetid://9126732571",
		"rbxassetid://9126732962",
		"rbxassetid://9126732962",
		"rbxassetid://9126732457",
		"rbxassetid://9126732862",
		"rbxassetid://9126732776",
		"rbxassetid://9126732334",
		"rbxassetid://9126732253"
	},
	
	["Snow"] = {
		"rbxassetid://9126732128",
		"rbxassetid://9126731099",
		"rbxassetid://9126732016",
		"rbxassetid://9126731951",
		"rbxassetid://9126731877",
		"rbxassetid://9126731632",
		"rbxassetid://9126731493",
		"rbxassetid://9126731343",
		"rbxassetid://9126731790",
		"rbxassetid://9126731243",
		"rbxassetid://9126731169",
		"rbxassetid://9126730861"
	},
	
	["Tile"] = {
		"rbxassetid://9126730713",
		"rbxassetid://9126730782",
		"rbxassetid://9126731037",
		"rbxassetid://9126730980",
		"rbxassetid://9126730651",
		"rbxassetid://9126730563",
		"rbxassetid://9126730279",
		"rbxassetid://9126730403",
		"rbxassetid://9126730056",
		"rbxassetid://9126730172",
		"rbxassetid://9126729836",
		"rbxassetid://9126730472",
		"rbxassetid://9126729938",
		"rbxassetid://9126729706"
	},
	
	["Wood"] = {
		"rbxassetid://9126931624",
		"rbxassetid://9126931515",
		"rbxassetid://9126931417",
		"rbxassetid://9126931322",
		"rbxassetid://9126931699",
		"rbxassetid://9126931235",
		"rbxassetid://9126931169",
		"rbxassetid://9126931026",
		"rbxassetid://9126930953",
		"rbxassetid://9126930885",
		"rbxassetid://9126930789",
		"rbxassetid://9126930647",
		"rbxassetid://9126930516",
		"rbxassetid://9126930598",
		"rbxassetid://9126930718"
	}
}

main.MaterialMap = {
	[Enum.Material.Slate] = 		main.SoundIds.Concrete,
	[Enum.Material.Concrete] = 		main.SoundIds.Concrete,
	[Enum.Material.Brick] = 		main.SoundIds.Concrete,
	[Enum.Material.Cobblestone] = 	main.SoundIds.Concrete,
	[Enum.Material.Sandstone] =		main.SoundIds.Gravel,
	[Enum.Material.Rock] = 			main.SoundIds.Gravel,
	[Enum.Material.Basalt] = 		main.SoundIds.Gravel,
	[Enum.Material.CrackedLava] = 	main.SoundIds.Concrete,
	[Enum.Material.Asphalt] = 		main.SoundIds.Concrete,
	[Enum.Material.Limestone] = 	main.SoundIds.Gravel,
	[Enum.Material.Pavement] = 		main.SoundIds.Concrete,

	[Enum.Material.Plastic] = 		main.SoundIds.Tile,
	[Enum.Material.Marble] = 		main.SoundIds.Tile,
	[Enum.Material.Neon] = 			main.SoundIds.Tile,
	[Enum.Material.Granite] = 		main.SoundIds.Tile,
	
	[Enum.Material.Wood] = 			main.SoundIds.Wood,
	[Enum.Material.WoodPlanks] = 	main.SoundIds.Wood,
	
	[Enum.Material.CorrodedMetal] = main.SoundIds.Metal_Solid,
	[Enum.Material.DiamondPlate] = 	main.SoundIds.Metal_Solid,
	[Enum.Material.Metal] = 		main.SoundIds.Metal_Solid,
	
	[Enum.Material.Foil] = 			main.SoundIds.Metal_Grate,
	
	[Enum.Material.Ground] = 		main.SoundIds.Dirt,
	
	[Enum.Material.Grass] = 		main.SoundIds.Grass,
	[Enum.Material.LeafyGrass] = 	main.SoundIds.Grass,
	
	[Enum.Material.Fabric] = 		main.SoundIds.Carpet,
	
	[Enum.Material.Pebble] = 		main.SoundIds.Gravel,
	
	[Enum.Material.Snow] = 			main.SoundIds.Snow,
	
	[Enum.Material.Sand] = 			main.SoundIds.Sand,
	[Enum.Material.Salt] = 			main.SoundIds.Sand,

	[Enum.Material.Ice] = 			main.SoundIds.Gravel,
	[Enum.Material.Glacier] = 		main.SoundIds.Gravel,
	[Enum.Material.Glass] = 		main.SoundIds.Glass,
	
	[Enum.Material.SmoothPlastic] = main.SoundIds.Rubber,
	[Enum.Material.ForceField] = 	main.SoundIds.Rubber,
	
	[Enum.Material.Mud] = 			main.SoundIds.Mud
}

-- This function produces a folder under a specified parent.
-- "soundProperties" is a table determining what the default properties of these audios will be.
function main:CreateSoundGroup(parent:Instance?, name:string?, soundProperties:{}?, isFolder:boolean?) : SoundGroup|Folder
	if not parent then warn("Parent not specified, Footstep folder parented to workspace") end
	isFolder = isFolder or false
	soundProperties = soundProperties or {}
	parent = parent or workspace
	-- Create folder
	local SoundGroup = nil
	if not isFolder then
		SoundGroup = Instance.new("SoundGroup"); SoundGroup.Volume = 1; SoundGroup.Name = name or "Footsteps"
	else
		SoundGroup = Instance.new("Folder"); SoundGroup.Name = name or "Footsteps"
	end
	local index = 0
	for soundMaterial,soundList in pairs(main.SoundIds) do
		index = 0
		local sectionGroup = nil
		if not isFolder then
			sectionGroup = Instance.new("SoundGroup"); sectionGroup.Volume = 1; sectionGroup.Name = soundMaterial
		else
			sectionGroup = Instance.new("Folder"); sectionGroup.Name = soundMaterial
		end
		for _,soundId in pairs(soundList) do
			index += 1 -- Increment index
			local soundEffect = Instance.new("Sound")
			soundEffect.Name = string.format("%s_%02i",soundMaterial:lower(),index)
			-- Set optional sound group
			if not isFolder then
				soundEffect.SoundGroup = sectionGroup
			end
			for property,value in pairs(soundProperties) do
				soundEffect[property] = value
			end
			soundEffect.SoundId = soundId
			soundEffect.Parent = sectionGroup
		end
		sectionGroup.Parent = SoundGroup
	end
	
	SoundGroup.Parent = parent
	return SoundGroup
end

-- This function returns a table from the MaterialMap given the material.
function main:GetTableFromMaterial(EnumItem : Enum.Material|string) : {}
	if typeof(EnumItem) == "string" then -- CONVERSION
		EnumItem = Enum.Material[EnumItem]
	end
	return main.MaterialMap[EnumItem]
end

local lastsoundid = nil

function main:GetRandomSound(SoundTable : {}) : string
	if SoundTable and #SoundTable > 0 then
		local newsoundid
		repeat
			newsoundid = math.random(#SoundTable)
		until newsoundid ~= lastsoundid

		lastsoundid = newsoundid 
		return SoundTable[newsoundid]
	else
		repeat wait(0.1) until SoundTable and #SoundTable > 0
		local newsoundid
		repeat
			newsoundid = math.random(#SoundTable)
		until newsoundid ~= lastsoundid

		lastsoundid = newsoundid  
		return SoundTable[newsoundid]
	end
end


return main
Sprinting Script

I’m aware of the problems attaching an event to a hotkey could cause and I will work to optimize it later.

local userinput = game:GetService("UserInputService")
local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local event = game.ReplicatedStorage:WaitForChild("running")
local event2 = game.ReplicatedStorage:WaitForChild("notrunning")


local sprintSpeed = 20
local slowSpeed = 7
local noSpeed = 0

local player = Players.LocalPlayer

local slow = true

local function tweenwalkspeed(targetSpeed, duration)
	local character = player.Character
	if not character then return end

	local humanoid = character:FindFirstChild("Humanoid")
	if not humanoid then return end

	local tweenInfo = TweenInfo.new(duration, Enum.EasingStyle.Linear, Enum.EasingDirection.Out)
	local goal = { WalkSpeed = targetSpeed }

	local tween = TweenService:Create(humanoid, tweenInfo, goal)
	tween:Play()
end

local function beginsprint(input, gameProcessed)
	if not gameProcessed then
		if input.UserInputType == Enum.UserInputType.Keyboard then
			local keycode = input.KeyCode
			if keycode == Enum.KeyCode.LeftShift then
				event:FireServer()
				tweenwalkspeed(sprintSpeed, 2) 
			end
		end
	end
end

local function endsprint(input, gameProcessed)
	if not gameProcessed then
		if input.UserInputType == Enum.UserInputType.Keyboard then
			local keycode = input.KeyCode
			if keycode == Enum.KeyCode.LeftShift then
				if slow == true then
					event2:FireServer()
					tweenwalkspeed(slowSpeed, 2) 
				else
					event:FireServer()
					tweenwalkspeed(player.Character.Humanoid.WalkSpeed, 0.5)
				end
			end
		end
	end
end

if player.Character and player.Character:FindFirstChild("Humanoid") then
	if player.Character.Humanoid.WalkSpeed == noSpeed then
		repeat wait() until player.Character.Humanoid.WalkSpeed > noSpeed

		userinput.InputBegan:Connect(beginsprint)
		userinput.InputEnded:Connect(endsprint)


	elseif player.Character.Humanoid.WalkSpeed > noSpeed then
		userinput.InputBegan:Connect(beginsprint)
		userinput.InputEnded:Connect(endsprint)
	end
end