AnimationTrack resets queue

In my game, there’ll be queues, where you can join a match by entering a part, and leave a part to not join the match.
However, my game also have attacks. You can use them by simply clicking the left mouse button. That is very simple, right? However, the attacks have animations, and somehow, the animations reset the countdown of the queue to teleport everyone to another place, where the game happens.

Here’s the script for QueueService:

--!strict

local CollectionService = game:GetService("CollectionService");
local ReplicatedStorage = game:GetService("ReplicatedStorage");
	local Networker = require(ReplicatedStorage.Packages.Networker);
	local Queue = require(ReplicatedStorage.Shared.Classes.Queue);
local Players = game:GetService("Players");
local RunService = game:GetService("RunService");
local TeleportService = game:GetService("TeleportService");

type Queue = Queue.Queue;

local QueueService = {};

type QueueService = typeof(QueueService) & {
	__setup: boolean,
	networker: Networker.Server,
	
	queues: {[BasePart]: Queue},
};

task.defer(function(self: QueueService)
	if self.__setup then return; end
	self.networker = Networker.Server.new("QueueService");
	
	self.queues = {};
	
	CollectionService:GetInstanceAddedSignal("Queue"):Connect(function(part: Instance)
		if not part:IsA("BasePart") then return; end
		
		local newQueue = Queue.new(part);
		self.queues[part :: BasePart] = newQueue;
		self:SetupQueue(newQueue);
	end)
	for _, part in CollectionService:GetTagged("Queue") do
		if not part:IsA("BasePart") then continue; end
		
		local newQueue = Queue.new(part)
		self.queues[part :: BasePart] = newQueue;
		self:SetupQueue(newQueue);
	end
	
	RunService.Heartbeat:Connect(function(delta: number)
		for _, queue: Queue in self.queues do
			local root = queue.root;
			
			local SurfaceGui: SurfaceGui = root:FindFirstChild("SurfaceGui") :: SurfaceGui;
			if not SurfaceGui then continue; end

			local TextLabel: TextLabel = SurfaceGui:FindFirstChild("TextLabel") :: TextLabel;
			if not TextLabel then continue; end
			
			if queue.countdown.Active then
				TextLabel.Text = `{15 - queue:GetEllapsedSeconds()} to teleport... ({#queue.players}/4)`;
				
				if 15 - queue:GetEllapsedSeconds() <= 0 then
					local access = TeleportService:ReserveServer(78382672946765) -- Reserve a server

					TeleportService:TeleportToPrivateServer(
						78382672946765,
						access,
						queue.players :: {Instance},
						nil,
						{},
						nil
					);
					table.clear(queue.players); -- Clears the table
				end
			else
				TextLabel.Text = `Waiting for more players to join... (0/4)`;
			end
		end
	end)
	
	self.__setup = true;
end, QueueService :: QueueService)

function QueueService.SetupQueue(self: QueueService, queue: Queue)
	-- Registering players
	queue.root.Touched:Connect(function(otherPart: BasePart)
		if #queue.players >= 4 then return; end
		
		if not otherPart.Parent then return; end
		if not otherPart.Parent.Parent then return; end
		
		local humanoid = otherPart.Parent:FindFirstChildOfClass("Humanoid") :: Humanoid or
			otherPart.Parent.Parent:FindFirstChildOfClass("Humanoid") :: Humanoid;

		local player = Players:GetPlayerFromCharacter(humanoid.Parent :: Model);
		if not player then return; end
		if table.find(queue.players, player) then return; end
		
		table.insert(queue.players, player);
		
		self:QueueUpdated(queue);
		print(otherPart)
	end)
	
	queue.root.TouchEnded:Connect(function(otherPart: BasePart)
		if not otherPart.Parent then return; end
		if not otherPart.Parent.Parent then return; end
		
		local humanoid = otherPart.Parent:FindFirstChildOfClass("Humanoid") :: Humanoid or
			otherPart.Parent.Parent:FindFirstChildOfClass("Humanoid") :: Humanoid;

		local player = Players:GetPlayerFromCharacter(humanoid.Parent :: Model);
		if not player then return; end

		table.remove(queue.players, table.find(queue.players, player));
		
		self:QueueUpdated(queue);
	end)
end

function QueueService.QueueUpdated(self: QueueService, queue: Queue)
	if #queue.players >= 1 then
		if not queue.countdown.Active then
			queue.countdown.Active = true;
			queue.countdown.Ellapsed = os.clock();
		end
	else
		queue.countdown.Active = false;
	end
end

return QueueService :: QueueService;

If you need the attack scripts or something else, please let me know!

1 Like

The problem is using Touched and TouchEnded. These aren’t super reliable for this use case. For example, if an animation has the player lift their legs, they might not be touching the part any more. Or sometimes the TouchEnded seems to fire randomly followed by a Touched even if contact wasn’t lost.

I would instead use a bounding box (just an invisible part) and use WorldRoot:GetPartsInPart() to get all the parts within the bounding box (and then the characters+players from the parts).

You could do the bounding box update every task.wait() or use the same Touched and TouchEnded events.

Very clean code btw.

Thank you :smiley:

Yeah, that might be the problem…

So I need to use spacial queries then.. ok, Thanks :smiley: