Needing help with Global & Material Based Footsteps

Trying to achieve a proficient Footsteps System that aims for Material Based perception and Global Footstep Sounds.

I already have a System in use atm, however I found it was beneficial in most ways.

[1] What to achieve - Footstep Sounds that are heard by other Clients and Footsteps depict on the Material region.

Figure 1 > I want to add Sound storage instead of using Module
Screenshot 2024-06-28 030854

Full Script > StarterPlayer > StarterCharacterScripts
Server Side >

-- Storages
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Players
local Players = game:GetService("Players")
local Player = Players:GetPlayerFromCharacter(script.Parent)
local Character = Player.Character or Player.CharacterAdded:wait()
local Humanoid = Character.Humanoid

-- Sound Variables
local ID
local Volume
local PlaybackSpeed

-- Material Variables
local FloorMaterial
local Material

-- Remote Instance
local UpdateWalkspeedRemote = game:GetService("ReplicatedStorage"):FindFirstChild("UpdateWalkspeed")
if UpdateWalkspeedRemote == nil then
	UpdateWalkspeedRemote = Instance.new("RemoteEvent", game.ReplicatedStorage)
	UpdateWalkspeedRemote.Name = "UpdateWalkspeed"
end

-- Sound Instance
local CurrentSound = Instance.new("Sound", Character.HumanoidRootPart)
	  CurrentSound.Name = "CurrentSound"
	  CurrentSound.RollOffMode = Enum.RollOffMode.Linear
	  CurrentSound.RollOffMinDistance = 10
	  CurrentSound.RollOffMaxDistance = 50


-- Fetch the ID List
local FootstepsModule = require(script:FindFirstChildWhichIsA("ModuleScript"))

-- Collect the current Floor Material
local function GetFloorMaterial()
	FloorMaterial = Humanoid.FloorMaterial
	Material = string.split(tostring(FloorMaterial), "Enum.Material.") [2]
	return Material
end

-- Collect the Sound List
local function GetSoundProperties()
	for Name, Data in pairs(FootstepsModule) do
		if Name == Material then
			ID = Data.ID
			Volume = Data.Volume
			PlaybackSpeed = (Humanoid.WalkSpeed / 10) * Data.Speed
			break
		end
	end
end

-- Update the Sound Data
local function SoundUpdate()
	CurrentSound.SoundId = ID
	CurrentSound.Volume = Volume
	CurrentSound.PlaybackSpeed = PlaybackSpeed
end

UpdateWalkspeedRemote.OnServerEvent:Connect(function(Player, Walkspeed)
	Player.Character.Humanoid.WalkSpeed = Walkspeed
end)

-- Moving Control (check Player isn't Climbing)
Humanoid.Running:Connect(function(Speed)
	if Humanoid.MoveDirection.Magnitude > 0 and Speed > 0 and Humanoid:GetState() ~= Enum.HumanoidStateType.Climbing then
		GetSoundProperties()
		SoundUpdate()
		CurrentSound.Playing = true
		CurrentSound.Looped = true
	else
		CurrentSound:Stop()
	end
end)

-- Solution to 'humanoid:GetPropertyChangedSignal("FloorMaterial")' not working as expected on the Server.
local ServerFix = coroutine.create(function()
	while task.wait() do
		if Humanoid.FloorMaterial ~= FloorMaterial then
			GetFloorMaterial()
			GetSoundProperties()
			SoundUpdate()
		end
	end
end)

if coroutine.status(ServerFix) == "suspended" then
	coroutine.resume(ServerFix)
end

Client Side

-- Services
local SoundService = game:GetService("SoundService")

-- Storages
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- Players
local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:wait()
local Humanoid = Character.Humanoid
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")

-- Sound Variables
local ID
local Volume
local PlaybackSpeed

-- Material Variables
local FloorMaterial
local Material

-- Collect the Global Audio
local ServerSound = HumanoidRootPart:WaitForChild("CurrentSound")

-- Remote Instance
local UpdateWalkspeedRemote = ReplicatedStorage:WaitForChild("UpdateWalkspeed")

-- Sound Instance
local CurrentSound = Instance.new("Sound", SoundService)
	  CurrentSound.Name = "CurrentSound"

-- fetch the ID List
local FootstepsModule = require(script.Parent:FindFirstChildWhichIsA("ModuleScript"))

-- Remove Default Footstep Sound
Character.HumanoidRootPart:FindFirstChild("Running"):Destroy()

-- Collect the current Floor Material
local function GetFloorMaterial()
	FloorMaterial = Humanoid.FloorMaterial
	Material = string.split(tostring(FloorMaterial), "Enum.Material.") [2]
	return Material
end

-- Collect the Sound List
local function GetSoundProperties()
	for Name, Data in pairs(FootstepsModule) do
		if Name == Material then
			ID = Data.ID
			Volume = Data.Volume
			PlaybackSpeed = (Humanoid.WalkSpeed / 10) * Data.Speed
			break
		end
	end
end

-- Update the Sound Data
local function SoundUpdate()
	CurrentSound.SoundId = ID
	CurrentSound.Volume = Volume
	CurrentSound.PlaybackSpeed = PlaybackSpeed
end

-- Initial Data for Client
GetFloorMaterial()
GetSoundProperties()
SoundUpdate()

-- Update < Floor Material & > Material
Humanoid:GetPropertyChangedSignal("FloorMaterial"):Connect(function()
	GetFloorMaterial()
	GetSoundProperties()
	SoundUpdate()

	if Humanoid.MoveDirection.Magnitude > 0 then
		CurrentSound.Playing = true
	end
end)

-- Server replicates the WalkSpeed has changed
Humanoid:GetPropertyChangedSignal("WalkSpeed"):Connect(function()
	UpdateWalkspeedRemote:FireServer(Humanoid.WalkSpeed)
end)

-- Moving Control (check Player isn't Climbing)
Humanoid.Running:Connect(function(Speed)
	if Humanoid.MoveDirection.Magnitude > 0 and Speed > 0 and Humanoid:GetState() ~= Enum.HumanoidStateType.Climbing then
		GetSoundProperties()
		SoundUpdate()
		CurrentSound.Playing = true
		CurrentSound.Looped = true
	else
		CurrentSound:Stop()
	end
end)

ServerSound.Changed:Connect(function(Volume)
	if Volume ~= 0 then
		ServerSound.Volume = 0
	end
end)

-- Small Big fix where the Sound would start Playing after the Player joined
Player.CharacterAdded:Connect(function()
	task.wait(1)
	if CurrentSound.IsPlaying then
		CurrentSound:Stop()
	end
end)

and the Module that I want to replace with Figure 1.
Module

local FootstepsModule = {
	Air = {ID = "rbxassetid://329997777", Volume = 0, Speed = 0},
	Asphalt = {ID = "rbxassetid://277067660", Volume = 0.55, Speed = 1.00},
	Basalt = {ID = "rbxassetid://3190903775", Volume = 0.55, Speed = 1.00},
	Brick = {ID = "rbxassetid://178190837", Volume = 0.55, Speed = 1.00},
	Cobblestone = {ID = "rbxassetid://178190837", Volume = 0.55, Speed = 1.00},
	Concrete = {ID = "rbxassetid://277067660", Volume = 0.55, Speed = 1.00},
	CorrodedMetal = {ID = "rbxassetid://177940974", Volume = 0.55, Speed = 1.00},
	CrackedLava = {ID = "rbxassetid://3190903775", Volume = 0.55, Speed = 1.00},
	DiamondPlate = {ID = "rbxassetid://177940974", Volume = 0.55, Speed = 1.00},
	Fabric = {ID = "rbxassetid://133705377", Volume = 0.55, Speed = 1.00},
	Foil = {ID = "rbxassetid://178190837", Volume = 0.55, Speed = 1.00},
	Forcefield = {ID = "rbxassetid://329997777", Volume = 0.55, Speed = 1.00},
	Glass = {ID = "rbxassetid://178190837", Volume = 0.55, Speed = 1.00},
	Granite = {ID = "rbxassetid://178054124", Volume = 0.55, Speed = 1.00},
	Grass = {ID = "rbxassetid://177940963", Volume = 0.55, Speed = 1.00},
	Glacier = {ID = "rbxassetid://7047108275", Volume = 0.55, Speed = 1.00},
	Ground = {ID = "rbxassetid://9064714296", Volume = 0.55, Speed = 1.00},
	Ice = {ID = "rbxassetid://7047108275", Volume = 0.55, Speed = 1.00},
	Limestone = {ID = "rbxassetid://9083846829", Volume = 0.55, Speed = 1.00},
	LeafyGrass = {ID = "rbxassetid://3098847639", Volume = 0.55, Speed = 1.00},
	Marble = {ID = "rbxassetid://178190837", Volume = 0.55, Speed = 1.00},
	Metal = {ID = "rbxassetid://177940974", Volume = 0.55, Speed = 1.00},
	Mud = {ID = "rbxassetid://6441160246", Volume = 0.55, Speed = 1.00},
	Neon = {ID = "rbxassetid://177940974", Volume = 0.55, Speed = 1.00},
	Pebble = {ID = "rbxassetid://178190837", Volume = 0.55, Speed = 1.00},
	Plastic = {ID = "rbxassetid://4416041299", Volume = 0.55, Speed = 1.40},
	Pavement = {ID = "rbxassetid://277067660", Volume = 0.55, Speed = 1.00},
	Rock = {ID = "rbxassetid://178190837", Volume = 0.55, Speed = 1.00},
	Sand = {ID = "rbxassetid://9083846829", Volume = 0.55, Speed = 1.00},
	Slate = {ID = "rbxassetid://178054124", Volume = 0.55, Speed = 1.00},
	Snow = {ID = "rbxassetid://8453425942", Volume = 0.55, Speed = 1.00},
	Salt = {ID = "rbxassetid://9083846829", Volume = 0.55, Speed = 1.00},
	Sandstone = {ID = "rbxassetid://3190903775", Volume = 0.55, Speed = 0.75},
	SmoothPlastic = {ID = "rbxassetid://178190837", Volume = 0.55, Speed = 1.00},
	Wood = {ID = "rbxassetid://178190837", Volume = 0.55, Speed = 1.00},
	WoodPlanks = {ID = "rbxassetid://211987063", Volume = 0.55, Speed = 1.00}
}

return FootstepsModule

Figure 1 will be located in SoundService unless is replaced or REMOVED.

1 Like