What do you want to achieve?
I’m trying to achieve a functioning footstep system that plays certain sounds depending on the material of the part the character walks on. It plays a sound when an animation event is reached in my run animation and plays a sound depending on the material of what’s underneath the character, which is found by raycasting.
What is the issue? Everything works fine-- the sound plays at the right time, the sounds change with the material-- except when I move to a new material, the sounds stack instead of changing. I’m very new to this so I have no idea how to fix this issue.
Here’s a video:
What solutions have you tried so far? I’ve tried searching this, but I’m not exactly sure how to word it-- feels too specific. I need sounds to not stack when a new one is picked from a table. I’d mess with my own script to try and get a solution but I have no clue where to even start.
Here’s the table that references the different placeholder step sounds. “Grass”, “Plastic”, and “Sand” are the names of sounds in workspace
here’s what loads the sounds and raycast. this snippet includes making the character sprint and it’s kinda messy, so I added some notes
UIS.InputBegan:Connect(function(Input: InputObject, Processed: boolean)
if not Processed then
if Input.UserInputType == Enum.UserInputType.Keyboard and Input.KeyCode == Key and Faster == true then
Humanoid.WalkSpeed = 35 -- make character faster
SprintingTween:Play() -- screen effect
print("runningfaster") -- old debug
sprintAnimTrack:Play(0) -- play animation
runService.RenderStepped:Connect(function() -- the raycasting
local ray = Ray.new(character:WaitForChild("HumanoidRootPart").Position, Vector3.new(0, -5, 0))
local part, pos, _, material = workspace:FindPartOnRayWithIgnoreList(ray, {character, workspace.Baseplate})
if part then
print(part.Name) -- prints what im standing on
if material then
print(material) -- prints material of what im standing on
end
local soundOfMat = materialSounds[material] -- goes into my sounds table and finds one with the same name as the material
if soundOfMat then -- if there is a sound with the same name
sprintAnimTrack:GetMarkerReachedSignal("FootStep"):Connect(function() -- when the animation reaches the marker
soundOfMat:Play() -- play the sound
end)
end
end
end)
again, im very new to scripting entirely, so please be patient with me if I don’t understand something/the solution is ridiculously obvious i feel like it is
let me know if you need anything else to help
Might be a dumb question, but how could I do this in the script? I can’t think of how without being unable to get it back for the next time I’m on that material
I tried creating the sounds depending on soundOfMat.Name but they are not created
runService.RenderStepped:Connect(function()
local ray = Ray.new(character:WaitForChild("HumanoidRootPart").Position, Vector3.new(0, -5, 0))
local part, pos, _, material = workspace:FindPartOnRayWithIgnoreList(ray, {character, workspace.Baseplate})-- Casting a ray
if part then
print(part.Name)
if material then
print(material)
end
local soundOfMat = materialSounds[material]
if soundOfMat then
if soundOfMat.Name == ("Enum.Material.Grass") then
local newsoundgrass = Instance.new("Sound")
newsoundgrass.Name = ("Grass")
newsoundgrass.Parent = game.Workspace
newsoundgrass.SoundId = "rbxassetid://507863105"
end
if soundOfMat.Name == ("Enum.Material.Plastic") then
local newsoundplastic = Instance.new("Sound")
newsoundplastic.Name = ("Plastic")
newsoundplastic.SoundId = "rbxassetid://4453297814"
newsoundplastic.Parent = game.Workspace
end
if soundOfMat.Name == ("Enum.Material.Sand") then
local newsoundsand = Instance.new("Sound")
newsoundsand.SoundId = "rbxassetid://265653329"
newsoundsand.Name = ("Sand")
newsoundsand.Parent = game.Workspace
end
sprintAnimTrack:GetMarkerReachedSignal("FootStep"):Connect(function()
soundOfMat:Play()
soundOfMat:Destroy()
end)
end
end
end)
if groundMaterial == "Plastic" then
if HRP:FindFirstChild("GrassSound") then
HRP:FindFirstChild("GrassSound"):Destroy
end
--create the plastic stepping sound
end
when your script detects a material, it should check for any sounds that might be existing previously and destroy them. After the sound is destroyed it should create the new sound
I understand how this would work, but when I try and use this for the script it still just does not create a new sound instance in workspace
here’s a snippet of the code (what i edited)
if material then
print(material)
end
local soundOfMat = materialSounds[material]
if soundOfMat then
print(soundOfMat)
if material.Name == ("Enum.Material.Grass") then
local grasssound = Instance.New("Sound")
grasssound.Name = ("Grass")
grasssound.Parent = game.Workspace
if game.Workspace:FindFirstChild("Plastic") then
game.Workspace:FindFirstCihld("Plastic"):Destroy()
end
if game.Workspace:FindFirstChild("Sand") then
game.Workspace:FindFirstCihld("Sand"):Destroy()
end
sprintAnimTrack:GetMarkerReachedSignal("FootStep"):Connect(function() -- when the animation reaches the marker
soundOfMat:Play() -- play the sound
end)
end
end
end
end)
material prints as “Enum.Material.Grass” when I’m standing on grass, so why doesnt the “if material.Name == (“Enum.Material.Grass”) then” create the sound instance?
You’re printing the material itself, not the name of the material. materials dont have names, its printing “Enum.Material.Grass” because the material is grass. You should try something like
if material == enum.Material.Grass then
--your code here
end
I tried doing it without before posting .Name, but it didn’t work so I tried with just in case and just left it as that when that didn’t work either. Even tried again without .Name to make sure
i’ve tried if material == Enum.Material.Grass then if material == ("Enum.Material.Grass") then if material == (Enum.Material.Grass) then
none work
Fixed this error. Still no dice
here’s how the script snippet is right now
UIS.InputBegan:Connect(function(Input: InputObject, Processed: boolean)
if not Processed then
if Input.UserInputType == Enum.UserInputType.Keyboard and Input.KeyCode == Key and Faster == true then
Humanoid.WalkSpeed = 35 -- make character faster
SprintingTween:Play() -- screen effect
print("runningfaster") -- old debug
sprintAnimTrack:Play(0) -- play animation
runService.RenderStepped:Connect(function() -- the raycasting
local ray = Ray.new(character:WaitForChild("HumanoidRootPart").Position, Vector3.new(0, -5, 0))
local part, pos, _, material = workspace:FindPartOnRayWithIgnoreList(ray, {character, workspace.Baseplate})
if part then
print(part.Name) -- prints what im standing on
if material then
print(material) -- prints material of what im standing on
end
local soundOfMat = materialSounds[material] -- goes into my sounds table and finds one with the same name as the material
if soundOfMat then
print(soundOfMat)
if material == Enum.Material.Grass then
local grasssound = Instance.new("Sound")
grasssound.Name = ("Grass")
grasssound.Parent = game.Workspace
if game.Workspace:FindFirstChild("Plastic") then
game.Workspace:FindFirstCihld("Plastic"):Destroy()
end
if game.Workspace:FindFirstChild("Sand") then
game.Workspace:FindFirstCihld("Sand"):Destroy()
end
sprintAnimTrack:GetMarkerReachedSignal("FootStep"):Connect(function() -- when the animation reaches the marker
soundOfMat:Play() -- play the sound
end)
end
end
end
end)
as of now all im trying to get to happen is the sound to create. i know it wont play i just need it to actually be made
Try to print something to the console if you touch grass, if it prints then you know that the if statement is correct and it has something to do with the creation of the sound.
FIGURED IT OUT-- this is what i get for messy code. The above if statement looking for soundOfMat was looking for a sound to already be made so it just didn’t run.
…but now the sound is created just about a thousand times. How can I get it to only be made once?
The sound is created when the raycast detects im standing on grass. Every single frame. It would still make multiple (correct me if im wrong).
I’m going to try making another if statement inside that detects if a sound named “Grass” already exists and to just return if so
Oookay so as soon as I fix one thing, there’s another issue. Sound is created fine. Only one is made and the right one is made on the right material. But the others don’t delete? I step on grass, grass sound is made. Then, I step on sand, and the sand sound is made, but grass is not deleted?
if material == Enum.Material.Grass then
if game.Workspace:FindFirstChild("Grass") then
return
else
local grasssound = Instance.new("Sound")
grasssound.Name = ("Grass")
grasssound.SoundId = "rbxassetid://507863105"
grasssound.Parent = game.Workspace
if game.Workspace:FindFirstChild("Plastic") then
game.Workspace:FindFirstCihld("Plastic"):Destroy()
end
if game.Workspace:FindFirstChild("Sand") then
game.Workspace:FindFirstCihld("Sand"):Destroy()
end
end
end
if material == Enum.Material.Sand then
if game.Workspace:FindFirstChild("Sand") then
return
else
local sandsound = Instance.new("Sound")
sandsound.Name = ("Sand")
sandsound.Parent = game.Workspace
sandsound.SoundId = "rbxassetid://265653329"
if game.Workspace:FindFirstChild("Plastic") then
game.Workspace:FindFirstCihld("Plastic"):Destroy()
end
if game.Workspace:FindFirstChild("Grass") then
game.Workspace:FindFirstCihld("Grass"):Destroy()
end
im essentially back to square one with the same issue but now longer code
local function OnFloorMaterialChanged()
print(Humanoid.FloorMaterial) --Enum.Material.Air
end
Humanoid:GetPropertyChangedSignal("FloorMaterial"):Connect(OnFloorMaterialChanged)
Just so you’re aware, you can detect floor material changes like this.
I actually tried this first, but my custom character’s humanoid hardly detected any materials for some reason. If I remember correctly it was just plastic and grass? Not 100% sure. Switched to raycasting because it worked on all materials