How to eliminate server tool lag?

https://gyazo.com/302f8a2c90479013983b05b33f5d8c23

So I send client → server via local script when tool is used. And then on the server script I create a pie that gets thrown. As you can see there is a lag before it gets thrown. How can I remove this lag?

1 Like

you can either
set network ownership of the pie to the client
or
instead of creating the pie on the server make it fire a event to every client and create the projectile on them while handling stuff like hit detection on server

2 Likes

Typically, visuals should be handled on the client.

You would create the pie on the client who activated it and send info to the server about the pie. On the server, you would calculate where the pie should be and handle any hit detection or important game logic. The server would then send the info about the pie to all the other clients which would calculate where the pie should be and create it on their client.

This system makes it so the pie is visible to all players and most importantly, the position of the pie is accurate for everyone.

If I create the pie on the client, how will other see it? Or do you mean create the pie for every players client?

I am already setting network ownership.

When you say “fire an event to every client and create the projectile on them”

Is it possible to send a message from client → client, or do I need to fire event from client to server and then back?

And if the pie is made on client, how can I move it through the server script? Aka how can the server detect if it hit the player if it only exists on the client?

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

local RemoteEvent = ReplicatedStorage.RemoteEvents:WaitForChild("ClownPieThrow")

-- SETTINGS
local FORWARD_POWER = 80    
local UPWARD_POWER = 55     
local ROTATION_FORCE = 0

local TEMPLATE = ReplicatedStorage
	:WaitForChild("ClownEquipment")
	:WaitForChild("PieTemplates")
	:WaitForChild("Pie") 


local function createAndLaunchPie(player, originCFrame)
	local pieClone = TEMPLATE:Clone()
	pieClone.Parent = workspace

	
	for _, obj in ipairs(pieClone:GetDescendants()) do
		if obj:IsA("Part") then
			obj:SetNetworkOwner(player)
		end
	end

	local mainPart = pieClone:FindFirstChild("Handle")
	if not mainPart then
		warn("Pie template missing Handle part")
		pieClone:Destroy()
		return
	end


	for _, obj in ipairs(pieClone:GetDescendants()) do
		if obj:IsA("Weld") or obj:IsA("WeldConstraint") then
			obj:Destroy()
		end
	end

	for _, part in ipairs(pieClone:GetChildren()) do
		if part:IsA("BasePart") and part ~= mainPart then
			local weld = Instance.new("WeldConstraint")
			weld.Part0 = mainPart
			weld.Part1 = part
			weld.Parent = mainPart
		end
	end

	local spawnCF = originCFrame * CFrame.new(0, 0, -2)
	mainPart.CFrame = spawnCF

	for _, part in ipairs(pieClone:GetChildren()) do
		if part:IsA("BasePart") then
			part.Anchored = false
			part.CanCollide = true
		end
	end

	local forward = originCFrame.LookVector
	local velocity =
		forward * FORWARD_POWER +
		Vector3.new(0, UPWARD_POWER, 0) -- upward arc

	mainPart.AssemblyLinearVelocity = velocity

	mainPart.AssemblyAngularVelocity = Vector3.new(
		math.random(-ROTATION_FORCE, ROTATION_FORCE),
		math.random(-ROTATION_FORCE, ROTATION_FORCE),
		math.random(-ROTATION_FORCE, ROTATION_FORCE)
	)


	game.Debris:AddItem(pieClone, 10)
end



RemoteEvent.OnServerEvent:Connect(function(player, hrpCFrame)
	if typeof(hrpCFrame) ~= "CFrame" then return end
	createAndLaunchPie(player, hrpCFrame)
end)

Edit: ah, my parts were union operations..

still curious about the other methods though

  1. Create the pie on the client of who activated the tool.
  2. Using a synced timer, send the info about the pie to the server.
    → Ideally, you should minimise the amount of user input as exploiters can spoof the data sent through remotes on the client.
  3. On the server, calculate where the pie should be and handle any hit detection or important game logic here.
  4. The server would then send the info about the pie to all the other clients which would recalculate the position of the pie and create it on their client.

This system is clean and scalable and furthermore, this is the type of system most devs go for.

Using network ownership is hard to scale and becomes a headache when there’s multiple different tools being used.

Server → Server or Client → Client communication is done through: BindableEvents

However, I don’t recommend sending a message from client → client as exploiters can easily change the data sent through remotes.

For your second question about how can the server detect, you would use remote events to communicate client → server about the pie.

you should probably set the network ownership to the server if you dont want the freeze frame

My code creates a velocity to move the part. What do you mean by calculate where the pie should be?

The only thing I can think of, is to create an invisible part on the server and run the same code?