Basically I have code that is suppose to get data from a function, but the data doesnt get returned in an instant, so how do I make it wait til the data gets returned?
Trigger Code
AnimateButton.Click:Connect(function()
displayMsg(true,'SELECT RIGS TO ANIMATE')
local s = getSelected()
print(s)
if s then
print(s)
end
end)
Function
local function getSelected()
uis.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.R then
print('Gettin selections')
local s = {}
for _, item in pairs(selectionService:Get()) do
if item:FindFirstChildOfClass('Humanoid') then
s[item.Name] = item
end
end
return s
end
end)
end
AnimateButton.Click:Connect(function()
displayMsg(true,'SELECT RIGS TO ANIMATE')
local s = nil
s = getSelected()
repeat
task.wait()
until (s ~= nil)
print(s)
end)
This didnt work, I made it print “Yes” after it S should be equal to something but it never is or something
displayMsg(true,'SELECT RIGS TO ANIMATE')
local s = getSelected()
local t = 30
repeat
task.wait() t -= 0.03
until (s ~= nil) or t <= 0
print('yes') -- never gets printed
displayMsg(false)
if s then
print(s)
else
warn('DID NOT SELECT ANY RIGS')
end
local function getSelected()
uis.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.R then
local Return = {}
print('Gettin selections')
for _, item in pairs(selectionService:Get()) do
if item:FindFirstChildOfClass('Humanoid') then
table.insert(Return, item)
end
end
return Return
end
end)
end
Just btw, I’m fairly certain this will cause a memory leak because the UIS.InputBegan connection is not disconnected and is reconnected every click of the UI button.
RBXScriptSignal has a /Wait method that yields the thread and then resumes with the arguments once the event is fired. So instead of /Connect, you could do:
local function getSelected()
local input, wasProcessed = UserInputService.InputBegan:Wait()
if not wasProcessed and input.KeyCode == Enum.KeyCode.R then
...
end
end
You could also put it in a loop to retry yielding in the case the user input something that wasn’t R or was processed.
local runService = game:GetService("RunService")
local function getSelected()
local items = nil
local connection = uis.InputBegan:Connect(function(input) -- store the connection so it can be disconnected later
if input.KeyCode == Enum.KeyCode.R then
print('Gettin selections')
local s = {}
for _, item in pairs(selectionService:Get()) do
if item:FindFirstChildOfClass('Humanoid') then
s[item.Name] = item
end
end
items = s -- set the items variable to 's'
end
end)
while not items do -- yield the thread until the 'items' variable isn't nil
runService.Heartbeat:Wait() -- wait every frame
end
connection:Disconnect() -- disconnect the input connection
return items -- return the data
end
this could possibly work, i haven’t tested it though:
local function getSelected()
local running = coroutine.running()
uis.InputBegan:Connect(function(input)
if input.KeyCode == Enum.KeyCode.R then
print('Gettin selections')
local s = {}
for _, item in pairs(selectionService:Get()) do
if item:FindFirstChildOfClass('Humanoid') then
s[item.Name] = item
end
end
coroutine.resume(running)
return s
end
end)
coroutine.yield()
end
no weird while loops, though I’m concerned about how you are not disconnecting the inputbegan event
You should look into using an open source module such as promise which provides a ton of methods for pausing the thread until data has been returned. https://eryn.io/roblox-lua-promise/