How to make sounds go from Client-Sided to Server-Sided?

i was browsing the Resource category, and found an amazing material-footstep script from @PsychosisIncarnate.

essentially how it works, depending on the material you walk on, different sounds play, and while it works client-sided, I wanted to get it to work server-sided so that way other people could hear your footsteps, and for my game, that’s really important.

here are the scripts, formatted as parent → script for ease of reading.

STARTERCHARACTERSCRIPTS, MAIN SCRIPT
local players = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")

local player = players:GetPlayerFromCharacter(script.Parent)
local character = player.Character or player.CharacterAdded:wait()
local humanoid = character.Humanoid

local id
local volume
local playbackSpeed

local floorMaterial
local material

local updateWalkspeedRemote = Instance.new("RemoteEvent", game.ReplicatedStorage)
	  updateWalkspeedRemote.Name = "UpdateWalkspeed"	

local currentSound = Instance.new("Sound", character.HumanoidRootPart)
	  currentSound.Name = "CurrentSound"
	  currentSound.RollOffMode = Enum.RollOffMode.Linear
	  currentSound.RollOffMinDistance = 10
	  currentSound.RollOffMaxDistance = 75


local IDList = require(script:FindFirstChildWhichIsA("ModuleScript"))

local function getFloorMaterial()
	floorMaterial = humanoid.FloorMaterial
	material = string.split(tostring(floorMaterial), "Enum.Material.")[2]

	return material
end

local function getSoundProperties()
	for name, data in pairs(IDList) do
		if name == material then
			id = data.id
			volume = data.volume

			playbackSpeed = (humanoid.WalkSpeed / 12) * data.speed
			break
		end
	end
end

local function update()
	currentSound.SoundId = id
	currentSound.Volume = volume
	currentSound.PlaybackSpeed = playbackSpeed
end

humanoid:GetPropertyChangedSignal("FloorMaterial"):Connect(function()	
	getFloorMaterial()
	getSoundProperties()
	update()

	if humanoid.MoveDirection.Magnitude > 0 then 
		currentSound.Playing = true
	end
end)

updateWalkspeedRemote.OnServerEvent:Connect(function(player, walkspeed)
	player.Character.Humanoid.WalkSpeed = walkspeed
end)

humanoid.Running:Connect(function(speed)
	if humanoid.MoveDirection.Magnitude > 0 and speed > 0 and humanoid:GetState() ~= Enum.HumanoidStateType.Climbing then
		getSoundProperties()
		update()
		currentSound.Playing = true
		currentSound.Looped = true
	else
		currentSound:Stop()
	end
end)
MAIN SCRIPT, CLIENT-SOUNDS SCRIPT
local players = game:GetService("Players")
local soundService = game:GetService("SoundService")
local replicatedStorage = game:GetService("ReplicatedStorage")

local player = players.LocalPlayer
local character = player.Character or player.CharacterAdded:wait()
local humanoid = character.Humanoid

local id
local volume
local playbackSpeed

local floorMaterial
local material

local root = character:FindFirstChild("HumanoidRootPart") or character:WaitForChild("HumanoidRootPart")

local serverSound = root:WaitForChild("CurrentSound")

local updateWalkspeedRemote = replicatedStorage:WaitForChild("UpdateWalkspeed")

local currentSound = Instance.new("Sound", soundService)
	  currentSound.Name = "CurrentSound"

local id_list = require(script.Parent:FindFirstChildWhichIsA("ModuleScript"))


local function getFloorMaterial()
	floorMaterial = humanoid.FloorMaterial
	material = string.split(tostring(floorMaterial), "Enum.Material.")[2]

	return material
end

local function getSoundProperties()
	for name, data in pairs(id_list) do
		if name == material then
			id = data.id
			volume = data.volume
			playbackSpeed = (humanoid.WalkSpeed / 16) * data.speed
			break
		end
	end
end

local function update()
	currentSound.SoundId = id
	currentSound.Volume = volume
	currentSound.PlaybackSpeed = playbackSpeed
end

getFloorMaterial()
getSoundProperties()
update()

humanoid:GetPropertyChangedSignal("FloorMaterial"):Connect(function()
	getFloorMaterial()
	getSoundProperties()
	update()

	if humanoid.MoveDirection.Magnitude > 0 then
		currentSound.Playing = true
	end
end)

humanoid:GetPropertyChangedSignal("WalkSpeed"):Connect(function()
	updateWalkspeedRemote:FireServer(humanoid.WalkSpeed)
end)

humanoid.Running:Connect(function(speed)
	if humanoid.MoveDirection.Magnitude > 0 and speed > 0 and humanoid:GetState() ~= Enum.HumanoidStateType.Climbing then
		getSoundProperties()
		update()
		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)

player.CharacterAdded:Connect(function()
	task.wait(1)
	if currentSound.IsPlaying then
		currentSound:Stop()
	end
end)
MAIN SCRIPT, ID LIST
local IDList = {
	Air = {id = "rbxassetid://329997777", volume = 0, speed = 1.40},
	CorrodedMetal = {id = "rbxassetid://177940974", volume = 0.60, speed = 1.20},
	DiamondPlate = {id = "rbxassetid://177940974", volume = 0.60, speed = 1.20},
	Fabric = {id = "rbxassetid://9083849830", volume = 0.40, speed = 1.20},
	Foil = {id = "rbxassetid://178190837", volume = 0.60, speed = 1.20},
	Forcefield = {id = "rbxassetid://329997777", volume = 0.60, speed = 1.20},
	Glass = {id = "rbxassetid://178190837", volume = 0.60, speed = 1.20},
	Granite = {id = "rbxassetid://178054124", volume = 0.60, speed = 1.20},
	Neon = {id = "rbxassetid://177940974", volume = 0.60, speed = 1.20},
	Marble = {id = "rbxassetid://178190837", volume = 0.60, speed = 1.20},
	Metal = {id = "rbxassetid://177940974", volume = 0.60, speed = 1.20},
	Pebble = {id = "rbxassetid://178190837", volume = 0.60, speed = 1.20},
	Plastic = {id = "rbxassetid://4416041299", volume = 0.60, speed = 1.40},
	SmoothPlastic = {id = "rbxassetid://178190837", volume = 0.60, speed = 1.20},
	Wood = {id = "rbxassetid://3199270096", volume = 0.60, speed = 1.20},
	
	Asphalt = {id = "rbxassetid://277067660", volume = 0.60, speed = 1.20},
	Basalt = {id = "rbxassetid://3190903775", volume = 0.60, speed = 1.20},
	Brick = {id = "rbxassetid://178190837", volume = 0.60, speed = 1.20},
	Cobblestone = {id = "rbxassetid://178190837", volume = 0.60, speed = 1.20},
	Concrete = {id = "rbxassetid://277067660", volume = 0.60, speed = 1.20},
	CrackedLava = {id = "rbxassetid://3190903775", volume = 0.60, speed = 1.20},
	Glacier = {id = "rbxassetid://7047108275", volume = 0.40, speed = 1.20},
	Grass = {id = "rbxassetid://9064714296", volume = 0.60, speed = 1.45},
	Ground = {id = "rbxassetid://9064714296", volume = 0.60, speed = 1.45},
	Ice = {id = "rbxassetid://7047108275", volume = 0.40, speed = 1.20},
	LeafyGrass = {id = "rbxassetid://3098847639", volume = 0.60, speed = 2.1},
	Limestone = {id = "rbxassetid://9083846829", volume = 0.60, speed = 1.20},
	Mud = {id = "rbxassetid://6441160246", volume = 0.60, speed = 2.2},
	Pavement = {id = "rbxassetid://277067660", volume = 0.60, speed = 1.20},
	Rock = {id = "rbxassetid://178190837", volume = 0.60, speed = 1.20},
	Salt = {id = "rbxassetid://9083846829", volume = 0.40, speed = 1.20},
	Sand = {id = "rbxassetid://9083846829", volume = 0.40, speed = 1.20},
	Sandstone = {id = "rbxassetid://3190903775", volume = 0.60, speed = 0.75},
	Slate = {id = "rbxassetid://178054124", volume = 0.60, speed = 1.45},
	Snow = {id = "rbxassetid://8453425942", volume = 0.60, speed = 1.20},
	WoodPlanks = {id = "rbxassetid://211987063", volume = 0.60, speed = 1.20}
}

return IDList

thank you for reading this, and hopefully helping me with this problem.

1 Like

You can re-code the system so it works event-based, when someone steps on sand, it fires a remote event to the server to notify the player has touched the sand, and the server fires another(or the same) remote-event to notify all clients that the certain player has touched the sand, so on the client, you can create a sound object and play it near the player’s position.

You shouldn’t create sound objects on the server as it might cause some performance issues, and this way you wouldn’t be changing the already existing system too much.

Good luck!

1 Like

im very new to coding so i don’t know how to do that exactly, but i’ll try and bash my head into it and see if it turns out alright, it’s gotten me this far, haha.

@TheRealANDRO no luck so far, i’ve got the framework set up but i have absolutely no idea how to code it in.

Kk! I can help you with this. You need to make a remote event in Replicated Storage. Then you can make it fire that in your local script and then do what you needed to do in the server.

i’ve got that already set up, i’ve got an events folder (it’s attached to a bunch of other systems) though im not sure how to code it in properly

image
it looks like this by the way, in case you want to take a look at it.

Sorry for the late reply but this should be fixed now; Other people should be able to hear your footsteps as intended. There seems to be a problem with humanoid:GetPropertyChangedSignal("FloorMaterial") in server scripts. It executes twice and then never runs again. Not sure how I would go about fixing this or if it’s a bug so I have applied a temporary solution for the problem.

TL;DR: get the script again and replace the main server script with the new one.

1 Like