As a developer, it is currently difficult to yield a thread until the DesiredAngle property of a Motor is met, demanding some improvisation with BindableEvents (at least to prevent yielding with repeat wait()).
My proposition comes about from both finding the lack of such a method (a DesiredAngleReached event, perhaps?) inconvenient for working with motors and reading an article by @Kampfkarren about avoiding the use of wait() when needing to yield a thread in situations like these, where he writes:
“Roblox has events for everything you could possibly be waiting for (and if it doesn’t make a feature request!)”
A rather makeshift and cumbersome workaround I fell back on, like I said, made use of BindableEvents and GetPropertySignalChanged:
local desiredAngleReachedEvent = Instance.new("BindableEvent")
Motor:GetPropertySignalChanged("CurrentAngle"):Connect(function()
if Motor.CurrentAngle == Motor.DesiredAngle then
desiredAngleReachedEvent:Fire()
end
end)
desiredAngleReachedEvent.Event:Wait()
print("Desired angle reached")
This, as suggested in the aforementioned post, could instead be an event of Motors themselves:
Motor.DesiredAngle == Motor.CurrentAngle could never be met, so your script would yield forever if you are waiting for such a signal. Not sure if that’s great practice for your code base. Also note that these are float properties, so you have to check within an epsilon threshold anyhow – they might not ever be exactly the same value.
The code is somewhat trivial for this. I think you are misinterpreting the advice to avoid wait() and using property changed events where you don’t have to (and I don’t think GetPropertyChangedSignal even works for physics properties(?)). You should avoid wait(), but you don’t need to avoid yielding using more well-timed events like Heartbeat/Stepped. That’s fine to use here.
This should work and is relatively clean:
local Heartbeat = game:GetService("RunService").Heartbeat -- or Stepped
function yieldUntilDesiredAngle(motor, timeout, minDeviation)
-- TODO: default timeout and minDeviation to sensible values (i.e. 30, 0.01)
local start = tick()
while tick() - start < timeout and math.abs(motor.CurrentAngle - motor.DesiredAngle) > minDeviation do
Heartbeat:Wait()
end
return tick() - start
end
This is clean because physics properties change every frame anyway. It’s unnecessary to use an event here to listen for CurrentAngle changes when not using an event is less roundabout/cumbersome and has the same effect (since the changed event would fire every frame, anyway).