What’s up gamers, I was working a new game recently and the need for material specific footsteps came up again, so after rewriting my preexisting system I decided to make public it so all Roblox games could be better with little effort.
Features:
You can hear other peoples footsteps (With adjustable range)
Time between steps varies based on speed
Very easy to customize
Pretty lightweight
Force specific parts to sound like a different material
Force specific parts to use a specific footstep sound
Easy to customize jump sound
Unique sounds for landing on different materials
Showcase (old version):
Click here to get the model (New Version)
Main Script
-- Created by Smile4 / Studio Storm --
if script.Parent:IsA("StarterCharacterScripts") then
return
end
-- Services --
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Debris = game:GetService("Debris")
-- Consts --
local SPEED_GATE = 10
local SPEED_MAXIMUM = 15
local MIN_DISTANCE = 0
local MAX_DISTANCE = 100
local FOOTSTEPS : Folder = ReplicatedStorage:WaitForChild("Footsteps")
local CHARACTER : Model = script.Parent
local HUMANOID : Humanoid = CHARACTER:WaitForChild("Humanoid")
local HUMANOID_ROOT_PART : Part = CHARACTER:WaitForChild("HumanoidRootPart")
local SKIN_VECTOR = Vector3.new(0.1, 0, 0.1)
local DELAY_UPPER = (0.33 * (SPEED_MAXIMUM / 17.5)) * (SPEED_MAXIMUM / SPEED_GATE)
-- Vars --
local LastMaterial : string = nil
local LastNum : number = nil
local Landing : boolean = false
-- Functions --
local function CastAndPlaySound(soundType : string, volume : number, hipHeightAdd : number)
local castParams = RaycastParams.new()
castParams.FilterDescendantsInstances = {CHARACTER, workspace.CurrentCamera}
castParams.FilterType = Enum.RaycastFilterType.Exclude
castParams.RespectCanCollide = true
local HipHeight = HUMANOID.HipHeight
if HUMANOID.RigType == Enum.HumanoidRigType.R6 then
HipHeight = 2
end
local cast = workspace:Blockcast(
CFrame.new(HUMANOID_ROOT_PART.Position),
HUMANOID_ROOT_PART.Size - SKIN_VECTOR,
Vector3.new(0, -1, 0) * (HipHeight + hipHeightAdd),
castParams
)
if cast then
local material : string = cast.Material.Name
local materialOveride : string = cast.Instance:GetAttribute("Material")
local soundOveride = cast.Instance:GetAttribute("SoundOveride")
if materialOveride ~= nil then
material = materialOveride
end
local soundTable : table
if soundOveride then
soundTable = FOOTSTEPS[soundType][soundOveride]:GetChildren()
else
soundTable = FOOTSTEPS[soundType][FOOTSTEPS[material]:GetAttribute("Value")]:GetChildren()
end
local newNum = math.random(#soundTable)
if LastMaterial == material and #soundTable ~= 1 then
while newNum == LastNum do
newNum = math.random(#soundTable)
end
end
local sound : Sound = soundTable[newNum]:Clone()
LastMaterial = material
LastNum = newNum
sound.Name = soundType
sound.Volume = volume
sound.RollOffMode = Enum.RollOffMode.Linear
sound.RollOffMinDistance = MIN_DISTANCE
sound.RollOffMaxDistance = MAX_DISTANCE
sound.Parent = HUMANOID_ROOT_PART
sound:Play()
Debris:AddItem(sound, sound.TimeLength + 0.1)
end
end
local function FootstepLoop()
if HUMANOID.Health <= 0 then
return
end
local walkSpeed = Vector3.new(HUMANOID_ROOT_PART.AssemblyLinearVelocity.X, 0, HUMANOID_ROOT_PART.AssemblyLinearVelocity.Z).Magnitude
local delayTime = math.clamp(0.33 * (SPEED_MAXIMUM / walkSpeed), 0.1, DELAY_UPPER)
if walkSpeed > SPEED_GATE and not Landing then
CastAndPlaySound("step", 0.33, 0.1)
end
task.delay(delayTime, FootstepLoop)
end
FootstepLoop()
local StateChanged = HUMANOID.StateChanged:Connect(function(OldState, NewState)
if NewState == Enum.HumanoidStateType.Jumping then
local sound : Sound = FOOTSTEPS.Jump:Clone()
sound.Name = "jump"
sound.Volume = 0.05
sound.RollOffMode = Enum.RollOffMode.Linear
sound.RollOffMinDistance = MIN_DISTANCE
sound.RollOffMaxDistance = MAX_DISTANCE
sound.Parent = HUMANOID_ROOT_PART
sound:Play()
Debris:AddItem(sound, sound.TimeLength + 0.1)
elseif NewState == Enum.HumanoidStateType.Landed then
CastAndPlaySound("land", 0.4, 2)
Landing = true
task.delay(0.2, function()
Landing = false
end)
end
end)
HUMANOID.Died:Once(function()
StateChanged:Disconnect()
end)
oh and if you use this in your game let me know!