The easy way to go about this is to use a .Magnitude check.
Make a separate script for the handling of the sound that runs a while ... do loop.
Get the .Position of the player twice with a set amount of time in between.
For example:
while true do
local playerPos1 = character.HumanoidRootPart.Position
task.wait(0.1)
local playerPos2 = character.HumanoidRootPart.Position
if (playerPos1 - playerPos2).Magnitude >= 10 then --//Set the number to the magnitude you want the sound to start playing
--//Handle the sound volume
end
end
Then if the .Magnitude reached over a specific amount, you can do some maths to determine how loud the sound will get dependent on how large the magnitude is.
Note: the smaller the task.wait time is, the more accurate it will be.
I’m not sure how efficient is this for long term side. As this may cause memory leaks etc.
I think it would be better to make functions after a check point(a part touch) that will run to check if the player is falling etc. Your code is a bit different from what the OP asked…
I think if we put our brains together we can find the best way for this.
I do have a plan ill try to recreate it as i can’t think on devfourm ill create a basic system that you can modify to your liking and someone else can maybe add some stuff to correct me if i am wrong.
As mentioned, it’s an easy script I was able to think up in a few seconds. It may not be efficient nor long-term, but it can at least harvest ideas for the OP to develop further with.
So far I know, LuaU is a garbage collecting script, so when the variables get replaced, there will be no pointer towards those values, so they are scrapped as soon as they are replaced. No memory leak. If you want to be sure, you can always make the variables before the loop like so:
local playerPos1
local playerPos2
while true do
playerPos1 = character.HumanoidRootPart.Position
task.wait(0.1)
playerPos2 = character.HumanoidRootPart.Position
if (playerPos1 - playerPos2).Magnitude >= 10 then --//Set the number to the magnitude you want the sound to start playing
--//Handle the sound volume
end
end
Seeing the title, description and video attached, I get the impression OP is after a way to play a sound dependent on how fast the player is falling. Longer fall = Faster speed = Louder sound. With .Magnitude of the first and last position of a player is accurate to depict when they fall and how fast they fall.
As for your .Touched suggestion, it’s a big workaround and takes a lot of maintenance to apply it to every situation where the player can possibly fall in the map. A single script working in the background to run a constant check based on the player position is therefore a lot more flexible and can be applied in every situation. If you want to optimise it as much as possible, you can use the .Touched boundary to disable and enable the script where necessary, so it only runs when it should be used.
i tryed making a code myself (i know its way to complicated)… but the sound keeps playing loud even when you jump
-- Insert the sound ID of the freefall sound you want to use
local soundId = "rbxassetid://3308152153"
-- Minimum and maximum falling speeds
local minSpeed = 0 -- Change this as per your requirement
local maxSpeed = 1000 -- Change this as per your requirement
-- Create a LocalScript in StarterPlayerScripts and add this code
-- Get the character and humanoid of the player
local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoid = character:WaitForChild("Humanoid")
-- Load the sound
local sound = Instance.new("Sound")
sound.SoundId = soundId
sound.Parent = workspace
-- Function to update the sound volume based on falling speed
local function updateSound()
local speed = humanoid:FindFirstChild("RootPart").Velocity.Y
local volume = (speed - minSpeed) / (maxSpeed - minSpeed)
volume = math.clamp(volume, 0, 0.1) -- Ensuring volume value stays between 0 and 1
sound.Volume = volume
end
-- Trigger the updateSound function as long as the player is falling
humanoid.FreeFalling:Connect(function(isFreeFalling)
if isFreeFalling then
sound:Play()
humanoid:MoveTo(character.HumanoidRootPart.Position)
humanoid.MoveToFinished:Wait()
else
sound:Stop()
end
end)
-- Continuously update the sound volume while the player is falling
humanoid:GetPropertyChangedSignal("FreeFalling"):Connect(function()
if humanoid.FreeFalling then
updateSound()
end
end)
So it would be something like a time for parkour but not really.
local StartPart = workspace.Model.Start
local EndPart = workspace.Model.End
local Sound = script.Parent.Sound
local SoundStarted = false
StartPart.Touched:Connect(function()
if SoundStarted == false then
SoundStarted = true
print("start")
Sound:Play()
for i = 20, 0, -1 do
task.wait(1)
if SoundStarted == true then
Sound.Volume += 0.25
end
end
end
end)
EndPart.Touched:Connect(function()
if SoundStarted == true then
Sound:Stop()
Sound.Volume = 1
SoundStarted = false
print("stop")
end
end)
I did test it you can change stuff of course and good luck with your game DON’T GIVE UP!
So Start part would be the part where is the hole or what you have there and the end part would be before landing on the ground.
Why not check to see if the player’s state has changed to freefall?
When that happens fire a loop that runs every .1 or .2 seconds and read the Player’s speed. Multiply the sound volume by a percentage of the speed value until the player is no longer freefalling.
This will give you a constant increase in the sound value and you can change how much the sound increases by the percentage value.
It’s probably a good idea to clamp the volume so you don’t blow out player’s eardrums.
Well then you can check until it’s like 5-7. Depending how long are you falling you can adjust the 20 seconds to what ever. This was just a sketch as the players state didn’t work for him.
I wouldn’t say that I’m the best coder. Everyone learns new things every day.
This is what i know/i have learnt. I do understand i don’t want to give a bad example.
Now I actually had some free time, I decided I wanted to find a solution for this.
I made it somewhat more efficient than my last suggestion, whereas my last script ran a continuous while .. do loop, the new script only runs a loop if the StateType of the Humanoid is equals to Freefall.
Not the most optimized, but I tried. Here is the code with a video preview.
LocalScript located in StarterPlayer → StarterCharacterScripts
local character = script.Parent
local windSound = script.wind_loop_02 --//Sound of your choice. This one is used in the video
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local humanoid = character.Humanoid
local hrpVelocity
local soundVelocity
windSound.Looped = true
windSound.Volume = 0
windSound:Play()
humanoid.StateChanged:Connect(function(oldState, newState)
if newState == Enum.HumanoidStateType.Landed then
windSound.Volume = 0
--//print("Landed.") - debugging
elseif newState == Enum.HumanoidStateType.Freefall then
while newState == Enum.HumanoidStateType.Freefall do
hrpVelocity = humanoidRootPart.Velocity.Y
if hrpVelocity <= 0 then
soundVelocity = math.abs(hrpVelocity)
if soundVelocity >= 75 then
windSound.Volume = (soundVelocity - 75) / 100
--//print(windSound.Volume) - debugging
end
end
task.wait(0.05)
end
end
windSound.Volume = 0
--//print("End fall.") - debugging
end)
It worked perfect for me…
but i changed some things for my game…
local character = script.Parent
local windSound = script.wind_loop_02 --//Sound of your choice. This one is used in the video
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local humanoid = character.Humanoid
local hrpVelocity
local soundVelocity
local currentVolume = 0
local targetVolume = 0
local minPlaybackSpeed = 0.5 -- Minimum playback speed of the sound
local maxPlaybackSpeed = 2 -- Maximum playback speed of the sound
windSound.Looped = true
windSound.Volume = 0
windSound:Play()
function updateSound()
local playbackSpeed = minPlaybackSpeed + (maxPlaybackSpeed - minPlaybackSpeed) * currentVolume
windSound.Volume = currentVolume * (0.0001 - humanoidRootPart.Velocity.Y / 700)
windSound.PlaybackSpeed = playbackSpeed
end
humanoid.StateChanged:Connect(function(oldState, newState)
if newState == Enum.HumanoidStateType.Landed then
targetVolume = 0
--//print("Landed.") - debugging
elseif newState == Enum.HumanoidStateType.Freefall then
targetVolume = 1
end
end)
game:GetService("RunService").Heartbeat:Connect(function()
currentVolume = currentVolume + (targetVolume - currentVolume) * 0.0005
updateSound()
end)
wind_loop_02 is not a valid member of LocalScript “Workspace.MRX_perte.LocalScript” - Client - LocalScript:2
Stack Begin - Studio
Script ‘Workspace.MRX_perte.LocalScript’, Line 2 - Studio - LocalScript:2
Stack End
local windSound = character:WaitForChild("wind_loop_02")
i tryed waitforchild but now i get this error:
Infinite yield possible on ‘Workspace.MRX_perte:WaitForChild(“wind_loop_02”)’ - Studio
Stack Begin - Studio
Script ‘Workspace.MRX_perte.LocalScript’, Line 2 - Studio - LocalScript:2
Stack End
local character = script.Parent
local windSound = game.Workspace:FindFirstChild("wind_loop_02")
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
local humanoid = character.Humanoid
local hrpVelocity
local soundVelocity
local currentVolume = 0
local targetVolume = 0
local minPlaybackSpeed = 0.5 -- Minimum playback speed of the sound
local maxPlaybackSpeed = 2 -- Maximum playback speed of the sound
if windSound then
windSound.Looped = true
windSound.Volume = 0
windSound:Play()
else
error("Sound 'wind_loop_02' not found in character hierarchy.")
end
function updateSound()
local playbackSpeed = minPlaybackSpeed + (maxPlaybackSpeed - minPlaybackSpeed) * currentVolume
windSound.Volume = currentVolume * (0.0001 - humanoidRootPart.Velocity.Y / 700)
windSound.PlaybackSpeed = playbackSpeed
end
humanoid.StateChanged:Connect(function(oldState, newState)
if newState == Enum.HumanoidStateType.Landed then
targetVolume = 0
--//print("Landed.") - debugging
elseif newState == Enum.HumanoidStateType.Freefall then
targetVolume = 1
end
end)
game:GetService("RunService").Heartbeat:Connect(function()
currentVolume = currentVolume + (targetVolume - currentVolume) * 0.0005
updateSound()
end)