Issues with a spawn function

I want to achieve a cooldown on a server script which won’t stop the script for other players as their are using it, the issue is that the spawn function i’ve used for that somehow makes the time for the tween longer than it should be, it sometimes takes up to 3 seconds for the tween to complete but the given time for the tween to complete is 0.5 seconds.

Localscript (UserInputService)
local SkillEvent = game.ReplicatedStorage.Events:WaitForChild("SkillEvent")
local UIS = game:GetService("UserInputService")
local player = game:GetService("Players").LocalPlayer
local Mouse = player:GetMouse()

UIS.InputBegan:Connect(function(InputKey,IsTyping)
    if not IsTyping then
        if InputKey.KeyCode == Enum.KeyCode.T then
            SkillEvent:FireServer("Invisible[T]")
        elseif InputKey.KeyCode == Enum.KeyCode.R then
            SkillEvent:FireServer("Fireball[R]",Mouse.Hit)
        end
    end
end)
Server script (Creates the intances)
local Players = game:GetService("Players")

Players.PlayerAdded:Connect(function(Player)
	local leaderstats = Instance.new("Folder",Player)
	leaderstats.Name = "leaderstats"
	
	local Strength = Instance.new("NumberValue",leaderstats)
	Strength.Name = "Strength"
	
	local NewPlayer = Instance.new("Folder",game.ServerStorage.Players)
	NewPlayer.Name = Player.Name
	
	local NewSkillsFolder = Instance.new("Folder",NewPlayer)
	NewSkillsFolder.Name = "SkillFolder"
	
	local InvisibleSkillBoolean = Instance.new("BoolValue",NewSkillsFolder)
	InvisibleSkillBoolean.Name = "IsInvisible"
	
	local InvisibleSkillCooldown = Instance.new("NumberValue",InvisibleSkillBoolean)
	InvisibleSkillCooldown.Name = "InvisibleCooldown"
	
	local FireballBoolean = Instance.new("BoolValue",NewSkillsFolder)
	FireballBoolean.Name = "ShotFireball"
	
	local FireballCooldown = Instance.new("NumberValue",FireballBoolean)
	FireballCooldown.Name = "FireballCooldown"
end)
Server script (The script that makes the character invisible)
local SkillEvent = game.ReplicatedStorage.Events:WaitForChild("SkillEvent")
local PartSpaceFolder = game.Workspace.PartSpaceFolder
local Fireballs = game.ServerStorage.Fireballs
local SkillsCooldown = 2.5
local TweenService = game:GetService("TweenService")
local InvisibleGoals = { Transparency = 1}
local VisibleGoals = { Transparency = 0}
local TWI = TweenInfo.new(0.5,Enum.EasingStyle.Sine,Enum.EasingDirection.InOut,0,false,0)


SkillEvent.OnServerEvent:Connect(function(Player,KEY,Mouse,Boolean)
	local Character = Player.Character
	local Humanoid = Character.Humanoid
	local SkillsFolder = game:GetService("ServerStorage"):FindFirstChild("Players"):FindFirstChild(Player.Name).SkillFolder
	if KEY == "Invisible[T]" then
		if not SkillsFolder.IsInvisible.Value then
			spawn(function()
				for _,Child in ipairs(Character:GetChildren()) do
					if Child:IsA("MeshPart") then
						local invisibletween = TweenService:Create(Child,TWI,InvisibleGoals)
						invisibletween:Play()
					elseif Child:IsA("Part") and Child.Name ~= "HumanoidRootPart" then
						local invisibletween = TweenService:Create(Child,TWI,InvisibleGoals)
						invisibletween:Play()
					elseif Child:IsA("Accessory") then
						for _,Child in ipairs(Child:GetChildren()) do
							if Child:IsA("MeshPart") then
								local invisibletween = TweenService:Create(Child,TWI,InvisibleGoals)
								invisibletween:Play()
							end
						end
					end
				end
				wait(SkillsCooldown)
				SkillsFolder.IsInvisible.Value = true
			end)
		elseif SkillsFolder.IsInvisible.Value then
			spawn(function()
				for _,Child in ipairs(Character:GetChildren()) do
					if Child:IsA("MeshPart") then
						local visibletween = TweenService:Create(Child,TWI,VisibleGoals)
						visibletween:Play()
					elseif Child:IsA("Part") and Child.Name ~= "HumanoidRootPart" then
						local visibletween = TweenService:Create(Child,TWI,VisibleGoals)
						visibletween:Play()
					elseif Child:IsA("Accessory") then
						for _,Child in ipairs(Child:GetChildren()) do
							if Child:IsA("MeshPart") then
								local visibletween = TweenService:Create(Child,TWI,VisibleGoals)
								visibletween:Play()
							end
						end
					end
				end
				wait(SkillsCooldown)
				SkillsFolder.IsInvisible.Value = false
			end)
		end
	end
end)

That might be a lag problem. Also TweenService shouldn’t be used server-sided, at least if not needed. If you don’t absolutely need to play the tween on the server, then my suggestion (and best solution) is to use :FireAllClients() and in a local script use .OnClientEvent and create the tween. This will make the TweenService much smoother, and won’t cause any duration problems. I’ve always used this method and it works perfectly for me.

The problem is not with the TweenService itself, i’ve noticed that if i remove the spawn functions that it would work without any extra cooldown time, but i need the spawn function so that if somebody else sets off the cooldown, it won’t stop other players from using it as the cooldown is server-sided.

Oh. If I understand right, you’re worried that if another player uses the move, the cooldown will change for every player?

Yes, it is server-sided which means the server will wait said cooldown, which means:
Player 1: Sets off cooldown
Server: Waits cooldown and sets to false after
Meanwhile the server is still waiting: Player 2: Tries to use skill but failes because server is stuck at the wait statement

Shouldn’t it be done that there is a check at the top? If the cooldown is still active, just drop the request. I don’t see why you’d need to wait.

Note: You cannot use the Mouse object on the server. It’s only for the client.

Because it is a skill, i don’t want players to wait a cooldown that has not been set off by them

The check would be player specific. Something like this:

  1. Make a table of players. Make sure whenever a player is added, a table with the key being their name is created.
  2. When the player activates the cooldown, add a field to the player’s table with the name of the skill and the time it was set off.
  3. Now, you can always check that table if the cooldown is still active or not timeStamp - currentTime > 0.

You shouldn’t worry about that? I don’t see your cooldown variable changing anywhere in the script, so I’m assuming the value will always stay 2.5. If so, don’t worry about that. RemoteEvents will only “work” for the player that fired/sent them.

Indeed, it is not changing because it uses the wait function:

Alright, i was thinking way to much about how the server could work, after testing it without the spawn functions it worked perfectly without and after using:
image
With these scripts:

Player1
if game.Players.LocalPlayer.Name == "Player1" then
	while wait(0.5) do
		game.ReplicatedStorage.Events.SkillEvent:FireServer("Invisible[T]")
	end
else script:Destroy()
end
Player2
if game.Players.LocalPlayer.Name == "Player2" then
	while wait(1) do
		game.ReplicatedStorage.Events.SkillEvent:FireServer("Invisible[T]")
	end
else script:Destroy()
end

I’ve seen now that it don’t have to worry about any cooldown problems as the script does not stop at the wait statement and no user could’ve used if it would’ve been stuck at it, thanks for the help.