Sound Not Working Properly

The sound for footsteps sounds really choppy and seems to lag alot

This is the script I use for playing the footstep sound effect:

local function playFootstepSound(leg, material)
	local sounds = footsteps.sounds[material]
	if not sounds then return end
	
	local random = Random.new()
	local soundId = sounds[random:NextInteger(1, #sounds)]
	
	if soundId and soundId ~= lastFootstepSound then
		lastFootstepSound = soundId
		
		local sound = Instance.new("Sound")
		sound.SoundId = soundId
		sound.RollOffMaxDistance = 100
		sound.RollOffMinDistance = 10
		sound.Volume = footsteps.volume[material] or 0.5
		sound.Parent = leg
		sound:Play()
		task.spawn(function()
			sound.Ended:Wait()
			sound:Destroy()
		end)
	else
		playFootstepSound(leg, material)
	end
end

Here’s what it looks like in game:

The issue somewhat seems to be the sound.Ended:Wait() because if I remove it and replace it with a wait() it seems to work fine. I’ve tried using wait(sound.TimeLength * sound.PlaybackSpeed) but that seems to only give me extremely small results (0 - 0.5) Any help would be appriciated, thanks!

UPDATE:
sound:Destroy() also seems to make the sounds break, as when I remove both sound.Ended:Wait() and sound:Destroy() is when it only works, but I need the sound to be destroyed so there isn’t a million sound instances in the players legs.

The reason your footsteps sounded choppy was that you were loading in these sounds and playing them simultaneously without giving it time to load in. You should provide the script with something that contains these sound objects and clone them.

Here is the code with the fix and I had to guess some of the things that were missing in the buggy code.

local character = game.Players.LocalPlayer.Character or game.Players.LocalPlayer.CharacterAdded:Wait()
local humnanoid : Humanoid = character:WaitForChild("Humanoid")

local random = Random.new()
local legattribute = "Leg"
local lastFootstepSound

local function playFootstepSound(leg, material)
	if leg:GetAttribute(legattribute) == true then return end
	
	--[[
	local sounds = footsteps.sounds[material]
	if not sounds then return end
	
	local soundId = sounds[random:NextInteger(1, #sounds)]
	--]]
	
	local chosenSound = script:GetChildren()[random:NextInteger(1, #script:GetChildren())]

	if chosenSound and chosenSound ~= lastFootstepSound then
		leg:SetAttribute(legattribute, true)

		lastFootstepSound = chosenSound

		local sound = chosenSound:Clone()
		--[[
		sound.SoundId = soundId
		sound.RollOffMaxDistance = 100
		sound.RollOffMinDistance = 10
		sound.Volume = footsteps.volume[material] or 0.5
		--]]
		sound.Parent = leg
		sound:Play()

		task.delay(sound.TimeLength, function()
			leg:SetAttribute(legattribute, nil)
			sound:Destroy()
		end)
	else
		playFootstepSound(leg, material)
	end
end

game["Run Service"].PostSimulation:Connect(function()
	if humnanoid.MoveDirection.Magnitude > 0 and humnanoid.FloorMaterial ~= Enum.Material.Air then
		if character:FindFirstChild("LeftFoot") then
			playFootstepSound(character:FindFirstChild("LeftFoot"), humnanoid.FloorMaterial.Name)
		elseif character:FindFirstChild("RightFoot") then
			playFootstepSound(character:FindFirstChild("RightFoot"), humnanoid.FloorMaterial.Name)
		end
	end
end)

Is there a way to somehow not have to have all of the sound objects? I’m using a module script to help keep the data of all of the soundId’s, volume setting, materials, and I don’t want to have a huge folder of sounds.

It’s good practice to have a huge folder with sounds so then can get cached onto the client (otherwise, it’ll have to re-download the sounds every time, which will suck for poor internet connections).

This person is correct, but also because having a huge folder of sounds isn’t necessarily bad for performance if that is what you are worried about. This will have negligible difference if you continue this way with having a large file of sounds as we aren’t living in the early days of computing.