How could I make it so footsteps are individual sounds?

I have been working on a little thing for a few weeks to a month now and I am not super skilled in scripting.

If you do not understand what I mean by the title, I mean as if each footstep audio is an individual audio, not a single track. For example, lets say we have 6 footstep noises. Every 0.5 seconds or so you walk, one of those sounds are randomly chosen to be played.

Here is a video that is kind of shows what I am going for.

If you pay close attention to the audio, some sounds are repeated, thus showing that the audios are randomly selected.

I would like it if someone could help me figure this out?

PS: I don’t really think this matters but I got the video off YouTube since my recording software is bugging out.

2 Likes

you can put a few sounds in a folder under the script, use the script to get the folder, then in a loop select a child from the folder randomly using something like local randomSound = folder:GetChildren[math.random(1, #folder:GetChildren)] and then using that you have your random sound. if you dont know how to play this sound or make a loop that would do this i would recommend learning more about scripting. TheDevKing on youtube has some really great tutorials that can help you learn how to script, by the way.

2 Likes

Instead of having lots of slightly different sounds, you could place a sound effect instance under the sound object to make the footsteps sound different. E.g. put a PitchShiftSoundEffect under the sound and change the octave value a little each time the sound is played.

This is easier to do than using lots of different sounds and also uses less memory

3 Likes

Will give this a shot. Thank you for helping!

2 Likes

I may do this for a few audios, thanks!

2 Likes

how close are you listening? to me it sounds fine. If i made it i wouldn’t even notice that tbh

2 Likes

Im a close listener lol, I also don’t mind if they repeat.

1 Like

here’s my own footstep system that I use, it’s material based and you can get some inspo from it if you like. goes in StarterCharacterScripts.

local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")

local player = Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local humanoid = char:WaitForChild("Humanoid")
local hrp = char:WaitForChild("HumanoidRootPart")

local footstepFolder = script:WaitForChild("FootstepSounds")

-- Settings
local BASE_WALK_SPEED = 14
local BASE_STEP_INTERVAL = 0.4
local stepCooldown = 0

-- Function to get interval based on current walk speed
local function getStepInterval()
	local speed = humanoid.WalkSpeed
	if speed <= 0 then return BASE_STEP_INTERVAL end
	return BASE_STEP_INTERVAL * (BASE_WALK_SPEED / speed)
end

local function trim(str)
	return (str:gsub("^%s*(.-)%s*$", "%1"))
end

-- Play a random sound for a given material
local function playFootstep(material)
	local matFolder = nil
	local materialName = material.Name:lower() -- lowercase for comparison

	-- Search all folders to find one whose name list contains this material
	for _, folder in ipairs(footstepFolder:GetChildren()) do
		if folder:IsA("Folder") then
			local names = string.split(folder.Name, "/")
			for _, name in ipairs(names) do
				if trim(name):lower() == materialName then
					matFolder = folder
					break
				end
			end
			
			if matFolder then break end
		end
	end

	if not matFolder then matFolder = footstepFolder["Plastic/SmoothPlastic"] end

	local sounds = matFolder:GetChildren()
	if #sounds == 0 then return end

	local chosen = sounds[math.random(1, #sounds)]:Clone()
	chosen.Parent = hrp
	chosen.RollOffMaxDistance = 50
	chosen.Volume = 0.2
	chosen:Play()

	game.Debris:AddItem(chosen, chosen.TimeLength + 0.1)
end

-- Detect footsteps
RunService.RenderStepped:Connect(function(dt)
	if humanoid.MoveDirection.Magnitude > 0 and humanoid:GetState() == Enum.HumanoidStateType.Running then
		stepCooldown -= dt
		if stepCooldown <= 0 then
			local rayOrigin = hrp.Position
			local rayDirection = Vector3.new(0, -5, 0)
			local params = RaycastParams.new()
			params.FilterDescendantsInstances = {char}
			params.FilterType = Enum.RaycastFilterType.Exclude

			local result = workspace:Raycast(rayOrigin, rayDirection, params)
			if result and result.Material then
				playFootstep(result.Material)
			end

			stepCooldown = getStepInterval()
		end
	else
		stepCooldown = 0
	end
end)

hierarchy:

2 Likes

My friends who are advanced in programming were able to help me with this problem, so here’s the scripts we used and what is required.

Remote Event titled “Footstep” in ReplicatedStorage

Default Script in ServerScriptStorage

local footstepsFolder = game.SoundService:WaitForChild("your audio folder here")
local RS = game:GetService("ReplicatedStorage")
local FSevent = RS:WaitForChild("Footstep")

FSevent.OnServerEvent:Connect(function(player)
	local Sounds = footstepsFolder["footstep folder in audio folder"]:GetChildren()
	local Sound = Sounds[math.random(1,#Sounds)]:Clone()
	Sound.Parent = player.Character.UpperTorso
	--Change all sounds to have PlayOnRemove property to true.
	Sound:Destroy()
end)

LocalScript in StarterPlayerScripts

local RS = game:GetService("ReplicatedStorage")
local FSevent = RS:WaitForChild("Footstep")
local player = game:GetService("Players").LocalPlayer

player.CharacterAdded:Wait()

local character = player.Character
local Humanoid = character:WaitForChild("Humanoid")
local IsRunning = false

Humanoid.Running:Connect(function(speed)
	if speed > 0 then
		IsRunning = true
	else
		IsRunning = false
	end
end)
task.spawn(function()
	while true do
		if IsRunning == true then
			FSevent:FireServer()
			wait(0.5)
		end
		task.wait(0)
	end
end)

And here’s a script made by my friend to remove the default footstep noise, PUT IN StarterCharacterScripts

local hrp = script.Parent:WaitForChild("HumanoidRootPart") 
local runSound  = hrp:WaitForChild("Running")
if runSound  then
	runSound:Destroy()
end

I hope this can help someone as much as it helped me.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.