I have a brick that gives your character armor when you touch it, and everything works well until I get to the part where it changes your walking sound to something more metallic.
Previously, I tried making the script change the sound ID of the running sound instance, but according to the output, it was indexing nil with the sound ID and I couldn’t get it to work. So I decided to instead destroy the running sound and replace it with a different one, but it’s also indexing nil with the sound instance. No matter what I do, it’s always indexing nil with the sound.
This is the script. I hope someone can point out what I’m doing wrong, I really need to know how to do this properly.
function onTouched(part)
local humanoid = part.Parent:FindFirstChildOfClass("Humanoid")
local debounce = false
if humanoid~=nil and not debounce then
debounce = true
humanoid.MaxHealth = 200
humanoid.Health = 200
local hrp = humanoid.Parent.HumanoidRootPart
hrp:FindFirstChild("Running"):Destroy()
local sound = script.Running:Clone()
sound.Parent = hrp
task.wait(0.5)
debounce = false
end
end
script.Parent.Touched:Connect(onTouched)
The error I’m getting is “attempt to index nil with ‘Destroy’” on line 9.
I have found this thread, which should have been extremely helpful for this:
But it didn’t have any information or solution that proved helpful to my code, as it seems. I appreciate any form of help on this.
The closest solution I can give to you is that you use the free Model “Remove Player Footsteps.” See how the Script defines the players Running Sound and finalise the Script to your benefit.
Hey Sani,
When the script attempts to destroy the sound, are you sure the object is still there? I am thinking that the script runs well the first time, but as there are multiple parts on a character, a millisecond later another part fires it and the part is already destroyed.
Are you able to provide some more information into changing the soundId?
Basically, I want to replace the player’s running sound with a different running sound after they touch the brick that gives them the armor. I already have the sound I need, I just need to figure out how to make the armor giver actually change the player’s running sound.
The closest solution I can give to you is that you use the free Model “Remove Player Footsteps.” See how the Script defines the players Running Sound and finalise the Script to your benefit.
I don’t know if the code used in such a script would be useful in a script that uses a touched event.
When the script attempts to destroy the sound, are you sure the object is still there?
Yes, I manually check the HumanoidRootPart through the explorer to see if the sound has been destroyed or not and it’s still there. I will redo the Sound ID change method and show you how I did it and tell you how it goes.
I have redone the Sound ID method. This is the code:
function onTouched(part)
local humanoid = part.Parent:FindFirstChildOfClass("Humanoid")
local debounce = false
if humanoid~=nil and not debounce then
debounce = true
humanoid.MaxHealth = 200
humanoid.Health = 200
local hrp = humanoid.Parent:FindFirstChild("HumanoidRootPart")
local sound = hrp:FindFirstChild("Running")
sound.SoundId = "rbxassetid://9113154968"
task.wait(0.5)
debounce = false
end
end
script.Parent.Touched:Connect(onTouched)
I have gotten the following error in the output after touching the part, from line 10:
attempt to index nil with ‘SoundId’
I don’t understand why it’s nil. It’s literally there if I check the directory on the explorer.
Ahhh, I think I realised what the problem is. Luckily the solution is very simple! I assume this is a server-sided script and that’s the issue. The sounds are on the local client, the server cannot see the player’s sounds if that makes sense. So the server is trying to access something it can’t find. The reason the sounds are on the client-side is so you don’t hear other people walking or jumping.
To fix this, all you have to do is move the script into a local script or use a RemoteEvent to tell a localscript to perform the task you want it to do.
That is very useful to know, but leaves me to wonder how I will accomplish the sound change through a local script even though the armor is given through a touched event. As far as I know, local scripts cannot operate from a part.
A remote event that triggers a function from a local script inside StarterPlayerScripts would probably work. I can fire an event from the server to the client, correct?
Yeah so what you can do is have one localscript under the player and have a server script which fires an event to the player with the details. The beauty of this is, you only need one local script to handle the incoming events.
If you need any help in doing this, feel free to ask!
I have made a local script with a function that is triggered by an event:
local storage = game:GetService("ReplicatedStorage")
local players = game:GetService("Players")
local event = storage.RunningArmor
local player = players.LocalPlayer
local character = player.Character
event.OnClientEvent:Connect(function()
local hrp = character:FindFirstChild("HumanoidRootPart")
local sound = hrp:FindFirstChild("Running")
sound.SoundId = script.Running.SoundId
end)
The function is triggered successfully, but I’m getting an error:
PlayerScripts.SoundChange:8: attempt to index nil with ‘FindFirstChild’
Same old nil issue and I have no idea why. Is it on my nose or is it really just not as simple as I think it should be?
I believe your script is firing before your character has enough time to load in, hence the nil when trying to search.
Maybe try
local storage = game:GetService("ReplicatedStorage")
local players = game:GetService("Players")
local event = storage.RunningArmor
local player = players.LocalPlayer
local character
player.CharacterAdded:Connect(function()
character = player.Character
end)
Probably a bit sloppy, haven’t tested it but should hopefully work
Hmmm, it seems that you need to use the remoteevent in this case. Sounds like footsteps cannot be found in Normal Scripts but only in LocalScripts only! However, Localscripts still has a place where it can be run on. Here are the list i got from creator hub
This means that you cannot put a localscripts inside workspace. So what you can do is you can put a local scripts inside a repliacted first. A remote event in ReplicatedStorage. And a serverside script inside a part. When a part hit something. You can transfer the hitting data to the remoteevent (ex. Player character) then your localscripts in replicated first gets the data and change your sound in the HumanoidRootPart!
I believe your script is firing before your character has enough time to load in, hence the nil when trying to search.
The event that starts the function fires when the player touches the brick, not immediately after the player joins. I don’t see how using CharacterAdded would help, but I’ll see what i can do with that.
This means that you cannot put a localscripts inside workspace. So what you can do is you can put a local scripts inside a repliacted first. A remote event in ReplicatedStorage. And a serverside script inside a part. When a part hit something. You can transfer the hitting data to the remoteevent (ex. Player character) then your localscripts in replicated first gets the data and change your sound in the HumanoidRootPart!
I did that, as shown in the 12th reply that I posted. I put the local script in StarterPlayerScripts. The issue, though, is that I get an error where the script can’t find the HumanoidRootPart for some reason I still don’t understand. The HRP is there, the sounds are there, the variable is set when I touch the part and I don’t know why it’s indexing nil.
I was wrong. Using CharacterAdded before getting the player’s character suddenly made the script work just as intended. I had a huge doubt on that but it actually worked perfectly.
Thank you. I will make sure to use this method if I run into this issue again.
Glad you got it working! The reason why we have to wait for the character to load in this instance is that the server runs the script as soon as it’s created and often times the character has not loaded in yet. The script still checks but can’t find the character so it concludes the character does not exist and gives us nil instead of the character.
So later on, when the player touches the part and the script runs again, the script uses the local variables we set when the script ran the first time. But because it couldn’t find the character, the script replaced player.Character with nil instead and consequently tried
local hrp = nil:FindFirstChild("HumanoidRootPart")
If you have any other questions or need help, never hesitate to ask