I am attempting to use the script to play a different sound when the player walks on different materials. So far so good, however it seems that I can not use a string in a variable to get a value from the a table. Here is my code:
local Character = Player.Character
local DefaultSound = Character.Head:WaitForChild("Running").SoundId
local FloorMaterials = {
[Enum.Material.Concrete] = "Concrete",
[Enum.Material.Grass] = "Grass",
[Enum.Material.Pebble] = "Pebble",
[Enum.Material.Metal] = "Metal"
}
local Grass = {2154046681,2154046895,2154047106,2154047325}
local Concrete = {2154040185,2154040376,2154040597}
local Pebble = {2154068078,2154068306,2154068522,2154068766}
local Metal = {1708956242,1708957364,1708957110,1708956822,1708956542}
local NewSound = function(ID)
if Character:FindFirstChild("HumanoidRootPart") then
local Sound = Instance.new("Sound", Character.HumanoidRootPart)
game:GetService("Debris"):AddItem(Sound,3)
Sound.SoundId = "rbxassetid://"..ID
Sound.Playing = true
end
end
local Step = function()
local Material = FloorMaterials[Character.Humanoid.FloorMaterial]
if Material then
--NewSound(Material[math.random(1,#Material)])
print(Material[math.random(#Material)])
end
end
In the function “Step”, the variable “Material” is the plain name of the material the player is walking on. I am trying to use this variable to get a random audio from one of the tables at the top of the script. However, attempting to use the variable to do this results in nil.
How do I go about using a variable to get a value from the table?
Here’s a suggestion, not sure if it’s very efficient though
local function GetFloor(Character)
for Material,_ in pairs(FloorMaterials) do
if Material == Character.Humanoid.FloorMaterial then
return Material
end
end
Try and tweak it to your script and see if that works!
If all you need is the name of the material then you don’t even need the table. You can just simply use .Name after the Enum and it’ll return the name for you.
local FloorMaterials = {
[Enum.Material.Grass.Value] = {2154046681,2154046895,2154047106,2154047325},
[Enum.Material.Concrete.Value] = {2154040185,2154040376,2154040597}
[Enum.Material.Pebble.Value] = {2154068078,2154068306,2154068522,2154068766}
[Enum.Material.Metal.Value] = {1708956242,1708957364,1708957110,1708956822,1708956542}
}
local Step = function()
local Material = FloorMaterials[Character.Humanoid.FloorMaterial.Value]
if Material then
--NewSound(Material[math.random(1,#Material)])
print(Material[math.random(#Material)])
end
end
I don’t see why @OP would use .Value over using the Enum? What use case would this serve over just using Enum.Material.Plastic? Your initial reply also just posts code, with no explanation as to why the OP should use .Value; some clarification would help.
When you attempt to index FloorMaterials, you’re doing so with random numbers between 1 and the length of the dictionary. FloorMaterials is not indexed by numbers, it’s indexed by EnumItems, so Material[math.random(#Material)] does not work. You also cannot get the length of a dictionary.
You can use this function to get a random item from any dictionary, just pass it FloorMaterials.
You could keep this function in a utils module, or you could precompute the FloorMaterials array when your script starts and remove all the caching stuff.
local optionsCache = {}
local function RandomFromDict(dict)
local options = optionsCache[dict]
if not options then
options = {}
for i,v in pairs(dict) do
table.insert(options, v)
end
optionsCache[dict] = options
end
return options[math.random(#options)]
end
It generates an array for the members of dict and caches it so it doesn’t have to keep regenerating the array, then gets a random item from the array via numerical index. This function is unsuitable if dict is extremely large, or if it keeps changing.