Sound is an interesting one. From experience though, trying to get sound to play at the same time is a real pain in the *** (I made a jank script to sync multiple speakers together).
The best option would be to change the Sound.TimePosition property of the sound so one is a bit offset from the other, and start playing both of them at the same time, but I doubt that offset will be kept, as the sound engine doesn’t want to play nice. (And this solution is what I mean by “faking time”)
Does your solution work?
Also, never ever use this for long wait times, it’s bad enough with short wait times
Though you probably noticed studio freezing for 5.35 seconds when you run this script
The use-case is for those who need very precise waiting (in things like audio systems which have to align properly) or those who need to wait a very small amount of time in short or no loops.
I had to wait 0.003 seconds between the creation and playback of sounds to prevent them from sounding hacky and slow. But by running a for loop it would do it instantly and not respect the time needed between the creation, playback and removal of my sounds.
But this function, like I said many times before. Is not made for everyone. It is made for those with a need for it.
I’m sorry, but for my project that this was originally and specifically made for it did matter. As a a very slight increase or decrease could cause very loud and annoying click noises that would break my ears.
For context: I was making a system that uses 0-3 base sounds that play frequencies to construct a new sound.
Ok, I took a closer look at the script and um, well let me just say, the way you prevent it from freezing up is flawed
local RenderStepped = game:GetService("RunService").Heartbeat
local function quickWait(waitTime)
local startTime = os.clock()
local currentTime = os.clock()
while os.clock() - startTime <= waitTime do
if os.clock() - currentTime >= 0.005 then
local st = os.clock() -- This is something I added to reach the wait time of Heartbeat:Wait()
RenderStepped:Wait()
print(os.clock() - st) -- Printing the wait time of Heartbeat:Wait()
currentTime = os.clock()
end
end
return os.clock() - startTime
end
task.wait(4)
while true do
print(quickWait(0.006))
end
I do not understand how the first call actually works as intended, but the subsequent calls get all messed up by the RenderStepped:Wait() (also, this should not be called RenderStepped as it is Heartbeat…). Heartbeat waits for around 0.0100 seconds (which seems to be the dead time between frames), and that makes your quickWait function very inaccurate
The only way to have wait times this precise is to freeze the game, by using the execution speed of the cpu to wait some amount. There is no getting around that/
On the first call, Heartbeat:Wait() is waiting for a very very small amount of time (0.00006659999780822545 seconds I got), which I cannot explain. If someone knows why that is, please make a reply
That can actually be a valid use case as the sound engine is (very likely) not tied to the framerate, and doesn’t have any functions to precisely handle when sounds should be played. In practically any other use case though, this is bad practice and useless
and yes, I know there is no way to prevent freezing in the very low wait times running multiple times in loops. But at least my function can wait small amounts a few times and works great when not used in a loop.
For example, text engines. My implementation for that spam calls task.wait() which makes everything inaccurate and usually takes 3 seconds or more than the actual time provided. However, with QuickWait the inaccuracy is decreased to 0.5 seconds. Or another example where you are using algorithms, without yielding you might crash, but spamming task.wait() will make the algorithm slower. However with QuickWait it can speed up the algorithm while yielding the algorithm a bit without timing out the code.
ok so uh
there’s this slightly hacky method that abuses task.defer
is nowhere near as accurate as this, but much more performant. (i have no frame drops, despite it pretty much going at 0.005 seconds per loop)
i also made another, sadly it does crash the program for a comically short period of time, but it’s about as accurate, and i have made a seperate function for both, that is basically a loop function with those waits
the loop functions are slightly different from the wait functions, so that it won’t immediately send the game to hell
defer spam and task.desynchronize/task.synchronize spam aren’t my own original idea tho, so i’m not gonna post it as a community resource, since it’s a really far cry from a fully original creation that contributes a bunch to roblox development, but since it’s something to consider a bit, i might as well
as you can see, dwait and dloop are not very accurate, while cwait and cloop are more accurate EDIT: i made dloop more accurate so have fun
unfortunately, cwait and cloop causes frame drops for me unlike dwait and dloop, but ig i should’ve expected that
if you’re wondering why the people who made the task.defer abuse made it,
yeah it’s for order of execution purposes, they wanna make it just late enough to be executed last, and just early enough to run right before the next frame, to prevent property tampering
they have better methods (or so they claim) now, so they don’t care that much that these methods are out
I agree with you on the execution, but I do not agree with the use case. If it’s accurate, this could have A LOT of very practical uses in scripting and games. Even OP himself stated that he needed it for game, it’s definitely more useful than you think.
Unfortunately, it’s not executed very well. I will not be using this.