Confusion with Tables

So I am trying to get the ColorValue of a inserted table inside the AlertQueue table and this is what I am doing. Hopefully reading the script kind of helps you understand what I am trying to do. (Some parts of the code have been cut out since it’s unrelated to my issue.)

Main part of LocalScript:

local AlertQueue = {}

game.ReplicatedStorage.Events.RemoteEvents.Notification.OnClientEvent:Connect(function(Table)
	table.insert(AlertQueue, {Table.Text, Table.Time, Table.Color})
	print(Table.Color) --correctly printing decimal
end)

So this is where it’s going wrong (same LocalScript):

local AlertQueue = {}

local function Alert()
	while true do
		if #AlertQueue ~= 0 then
			local Task = table.remove(AlertQueue, 1)
			local Text = Task.Text
			local Time = Task.Time
			local Color = Task.Color
			print(Text) --returning nil/erroring out
		else
			wait()
		end
	end
end

spawn(Alert)

game.ReplicatedStorage.Events.RemoteEvents.Notification.OnClientEvent:Connect(function(Table)
	table.insert(AlertQueue, {Table.Text, Table.Time, Table.Color})
	print(Table.Color) --correctly printing decimal
end)
2 Likes

You are inserting into table the 3 values but without a key, like this:
{"waka", 15, "hexaNumber"}

And trying to get them as if the table looks like this:
{Text = "waka", Time = 15, Color = "hexaNumber"}

So, insert them with a key:

game.ReplicatedStorage.Events.RemoteEvents.Notification.OnClientEvent:Connect(function(Table)
	table.insert(AlertQueue, {Text = Table.Text, Time = Table.Time, Color = Table.Color})
	print(Table.Color) --correctly printing decimal
end)

And this other part I just changed some order:

local function Alert()
	while true do
		if #AlertQueue ~= 0 then
			warn(AlertQueue[1]["Text"])
			warn(AlertQueue[1]["Time"])
			warn(AlertQueue[1]["Color"])
			
			table.remove(AlertQueue, 1)
		else
			wait()
		end
	end
end

The idea is to always remove the first key by using a loop?

2 Likes

Oh my gosh this part made me feel sooo dumb lol. Thank you!! Something that has arisen was that the actual queue is not working, it’s just not queuing. Maybe you could take a look at my full script and see what’s going on? Thank you again!

local SoundModule = require(game.ReplicatedStorage.Modules.SoundModule)
local TweenService = game:GetService("TweenService")
local TransitionInfo = TweenInfo.new(0.3, Enum.EasingStyle.Quad)
local Order = 1
local AlertQueue = {}

local function Alert()
	while true do
		if #AlertQueue ~= 0 then
			local Text = AlertQueue[1]["Text"]
			local Time = AlertQueue[1]["Time"]
			local Color = AlertQueue[1]["Color"]
			table.remove(AlertQueue, 1)
			local AlertLabel = script.Assets.AlertLabel
			local NewAlertLabel = AlertLabel:Clone()
			NewAlertLabel.Name = "Alert"
			NewAlertLabel.BackgroundColor3 = Color
			NewAlertLabel.Text = Text
			NewAlertLabel.LayoutOrder = Order
			Order += 1
			NewAlertLabel.Parent = script.Parent.GUIHolder
			TweenService:Create(NewAlertLabel, TransitionInfo, {BackgroundTransparency = 0}):Play()
			TweenService:Create(NewAlertLabel, TransitionInfo, {TextTransparency = 0}):Play()
			SoundModule.PlaySound("Notification", "Client")
			local TweenWait = TweenService:Create(NewAlertLabel, TransitionInfo, {Position = UDim2.new(0.5, 0, 0.94, 0)})
			TweenWait:Play()
			
			TweenWait.Completed:Connect(function()
				wait(Time)
				TweenService:Create(NewAlertLabel, TransitionInfo, {BackgroundTransparency = 1}):Play()
				TweenService:Create(NewAlertLabel, TransitionInfo, {TextTransparency = 1}):Play()
				local TweenWait = TweenService:Create(NewAlertLabel, TransitionInfo, {Position = UDim2.new(0.5, 0, 0.88, 0)})
				TweenWait:Play()
				
				TweenWait.Completed:Connect(function()
					NewAlertLabel:Destroy()
				end)
			end)
		else
			wait()
		end
	end
end

spawn(Alert)

game.ReplicatedStorage.Events.RemoteEvents.Notification.OnClientEvent:Connect(function(Table)
	table.insert(AlertQueue, {Text = Table.Text, Time = Table.Time, Color = Table.Color})
end)
1 Like

Sure, I can give it a check, just, any more detailed symptom beside “not queuing” ?
output errors, anything?

2 Likes

Yeah! Sorry my explanation was pretty vague. Pretty much I have a module that’s giving me notifications when I do actions, such as pressing buttons in game (bricks with ClickDetectors). The notification just says that I pressed button and the button name ("You pressed button "…Button.Name) along with the BrickColor, and the time of how long I want the notification to be on screen.

Now when I press a lot of these buttons I get all the notifications as I press them, when really they should be queuing up, but they don’t. Hopefully that helps!

I think I see the issue.

When you create the TweenWait that will play the Tween, and you connect the event that when it completes it should wait the time, its not actually waiting that time. Its like that event you connected has no control over the task of the while loop iteration. So after the TweenWait is created it will not wait at all, it just has a function connected to the event that will perform something after is completed.

So after the TweenWait is created it will go to the next iteration of the while loop, resulting on creating the next notification, and so on with the rest.

Something you could do to force the thread to not continue until the TweenWait is completed and the wait(Time) inside its done too, is by using repeat until to yield the iteration, like this:

local TweenComplete = false -- a "lock" to force the yield

local TweenWait = TweenService:Create(NewAlertLabel, TransitionInfo, {Position = UDim2.new(0.5, 0, 0.94, 0)})
TweenWait:Play()

TweenWait.Completed:Connect(function()
	task.wait(Time)
	TweenComplete = true -- open the lock to continue with the next notification creation

	TweenService:Create(NewAlertLabel, TransitionInfo, {BackgroundTransparency = 1}):Play()
	TweenService:Create(NewAlertLabel, TransitionInfo, {TextTransparency = 1}):Play()
	local TweenWait = TweenService:Create(NewAlertLabel, TransitionInfo, {Position = UDim2.new(0.5, 0, 0.88, 0)})
	TweenWait:Play()

	TweenWait.Completed:Connect(function()
		NewAlertLabel:Destroy()
	end)
end)

repeat
	task.wait() -- Yield until tween completed
until TweenComplete

task.wait()
1 Like

This makes sense kind of, i’ve never really dealt with queues so thank you for your support.

So something like this would solve my issue?:

local SoundModule = require(game.ReplicatedStorage.Modules.SoundModule)
local TweenService = game:GetService("TweenService")
local TransitionInfo = TweenInfo.new(0.3, Enum.EasingStyle.Quad)
local Order = 1
local TweenComplete = false --new
local AlertQueue = {}

local function Alert()
	while true do
		if #AlertQueue ~= 0 then
			local Text = AlertQueue[1]["Text"]
			local Time = AlertQueue[1]["Time"]
			local Color = AlertQueue[1]["Color"]
			table.remove(AlertQueue, 1)
			local AlertLabel = script.Assets.AlertLabel
			local NewAlertLabel = AlertLabel:Clone()
			NewAlertLabel.Name = "Alert"
			NewAlertLabel.BackgroundColor3 = Color
			NewAlertLabel.Text = Text
			NewAlertLabel.LayoutOrder = Order
			Order += 1
			NewAlertLabel.Parent = script.Parent.GUIHolder
			TweenService:Create(NewAlertLabel, TransitionInfo, {BackgroundTransparency = 0}):Play()
			TweenService:Create(NewAlertLabel, TransitionInfo, {TextTransparency = 0}):Play()
			SoundModule.PlaySound("Notification", "Client")
			local TweenWait = TweenService:Create(NewAlertLabel, TransitionInfo, {Position = UDim2.new(0.5, 0, 0.94, 0)})
			TweenWait:Play()
			
			TweenWait.Completed:Connect(function()
				task.wait(Time) --was: wait(Time)
				TweenComplete = true --new
				TweenService:Create(NewAlertLabel, TransitionInfo, {BackgroundTransparency = 1}):Play()
				TweenService:Create(NewAlertLabel, TransitionInfo, {TextTransparency = 1}):Play()
				local TweenWait = TweenService:Create(NewAlertLabel, TransitionInfo, {Position = UDim2.new(0.5, 0, 0.88, 0)})
				TweenWait:Play()
				
				TweenWait.Completed:Connect(function()
					NewAlertLabel:Destroy()
				end)
			end)
			
			repeat --new
				task.wait() -- Yield until tween completed --new
			until TweenComplete --new
			
			task.wait() --new
		else
			wait()
		end
	end
end

spawn(Alert)

game.ReplicatedStorage.Events.RemoteEvents.Notification.OnClientEvent:Connect(function(Table)
	table.insert(AlertQueue, {Text = Table.Text, Time = Table.Time, Color = Table.Color})
end)
1 Like

Yup, but the “lock” cant be a global variable, it has to be unique per iteration, unless you constantly “close” it by setting it to false again. Would be better to simply create a new one per iteration:

local SoundModule = require(game.ReplicatedStorage.Modules.SoundModule)
local TweenService = game:GetService("TweenService")
local TransitionInfo = TweenInfo.new(0.3, Enum.EasingStyle.Quad)
local Order = 1
local AlertQueue = {}

local function Alert()
	while true do
		if #AlertQueue ~= 0 then
			local Text = AlertQueue[1]["Text"]
			local Time = AlertQueue[1]["Time"]
			local Color = AlertQueue[1]["Color"]
			table.remove(AlertQueue, 1)
			local AlertLabel = script.Assets.AlertLabel
			local NewAlertLabel = AlertLabel:Clone()
			NewAlertLabel.Name = "Alert"
			NewAlertLabel.BackgroundColor3 = Color
			NewAlertLabel.Text = Text
			NewAlertLabel.LayoutOrder = Order
			Order += 1
			NewAlertLabel.Parent = script.Parent.GUIHolder
			TweenService:Create(NewAlertLabel, TransitionInfo, {BackgroundTransparency = 0}):Play()
			TweenService:Create(NewAlertLabel, TransitionInfo, {TextTransparency = 0}):Play()
			SoundModule.PlaySound("Notification", "Client")
			------------------------------------------------
			local TweenComplete = false -- The lock
			
			local TweenWait = TweenService:Create(NewAlertLabel, TransitionInfo, {Position = UDim2.new(0.5, 0, 0.94, 0)})
			TweenWait:Play()

			TweenWait.Completed:Connect(function()
				task.wait(Time) --was: wait(Time)
				TweenComplete = true --new
				TweenService:Create(NewAlertLabel, TransitionInfo, {BackgroundTransparency = 1}):Play()
				TweenService:Create(NewAlertLabel, TransitionInfo, {TextTransparency = 1}):Play()
				local TweenWait = TweenService:Create(NewAlertLabel, TransitionInfo, {Position = UDim2.new(0.5, 0, 0.88, 0)})
				TweenWait:Play()

				TweenWait.Completed:Connect(function()
					NewAlertLabel:Destroy()
				end)
			end)

			repeat --new
				task.wait() -- Yield until tween completed --new
			until TweenComplete --new

			task.wait() --new
		else
			wait()
		end
	end
end

spawn(Alert)

game.ReplicatedStorage.Events.RemoteEvents.Notification.OnClientEvent:Connect(function(Table)
	table.insert(AlertQueue, {Text = Table.Text, Time = Table.Time, Color = Table.Color})
end)
2 Likes

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.