What do you want to achieve? Keep it simple and clear!
I don’t want the delay when adding the part (shown below)
What is the issue? Include screenshots / videos if possible! robloxapp-20250309-1846400.wmv (762.8 KB)
(sorry for the bad quality)
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I haven’t looked for any solutions, and I don’t know how to start fixing this problem (so much help would be appreciated)
here is my Script + object structure:
code for server script in ServerScriptService called Server:
local SC = require(game.ReplicatedStorage:WaitForChild("Modules"):WaitForChild("Constructors"):WaitForChild("SwordConstructor"))
game.Players.PlayerAdded:Connect(function(plr)
local plrSword
game.ReplicatedStorage.Events.Swap.OnServerEvent:Connect(function(plr)
if plrSword == nil then
plrSword = SC.New("WoodenSword")
else
plrSword = nil
end
end)
game.ReplicatedStorage.Events.E.OnServerEvent:Connect(function(plr)
if plrSword then
plrSword:Swing(plr)
end
end)
end)
code for client script in StarterPlayerScripts called Client:
local UIS = game:GetService("UserInputService")
UIS.InputBegan:Connect(function(input, g)
if g then return end
if input.KeyCode == Enum.KeyCode.One then
game.ReplicatedStorage.Events.Swap:FireServer()
elseif input.KeyCode == Enum.KeyCode.E then
game.ReplicatedStorage.Events.E:FireServer()
end
end)
Code for the module script named SwordConstructor:
local Sword = {}
Sword.__index = Sword
local Data = game.ReplicatedStorage.Modules.Data
local Debounce = false
local Combo = 1
local ComboReset = false
function Sword.New(Name)
local newSword = require(Data:FindFirstChild(Name))
setmetatable(newSword, Sword)
Combo = 1
return newSword
end
function Sword:Swing(Player, Position)
if Debounce then return end
local hitPart = game.ServerStorage:FindFirstChild(self.Name):FindFirstChild(Combo):Clone()
hitPart.Parent = workspace
hitPart.CFrame = CFrame.new((Player.Character.HumanoidRootPart.Position + Player.Character.HumanoidRootPart.CFrame.LookVector*10), Player.Character.HumanoidRootPart.Position)
print(self.Name)
print(Combo)
Debounce = true
task.wait(self.Debounce[Combo])
if Combo + 1 > #self.Debounce then
Combo = 1
else
Combo += 1
end
Debounce = false
end
return Sword
You invite latency at every turn when you involve the server. There is a natural delay between your movements and their replication to the server, so it’s apparent as to why this is happening. The solution is to not involve the server in collision detection. Keep that on the client for maximum responsiveness. The server will be informed of the client’s detected collisions and will verify their sanctity through sanity checks.
On another note, the most appropriate collision detection method for melee weapons is multi-ray casting. There are open-source technologies you can consider, such as ClientCast and RaycastHitboxV4.
Finally, if this is not intentional, your server-sided code cannot support multiplayer. Your Sword class is set up as a singleton, so each player will share state and cause corruption. Furthermore, your input events will duplicate each time a player enters the game, causing additional adverse effects and most of all, a memory leak
Thank you for the response. Much appreciated information and I will definitely have a closer look at the collision detection later. At the moment, though, I am more concerned with the issues with the singleton pattern and the memory leak. Would you mind explaining that a bit more?
You indicated that the issue is that the Sword class is a singleton, and with the addition of sharing state among players, it leads to corruption. My primary concern is the memory leak as the input events are being duplicated with the addition of a new player, which could have severe performance implications. I’d like to see more information on how this arrangement is affecting memory and if patterns or best practice exist that could address the issue.
Along with that, could you provide me with information on how to refactor the server code to manage multiuser interactions in the proper way so that a separate state for each player will exist without the risk of unwanted side effects? Thank you again.
Just have a .init function that runs once when the server starts where you connect all your events to, and then use the player parameter to find the correct sword object. And do the hit detection all on the client
You’re trying to apply OOP in this scenario. For objects to have individualized properties, they must be tied to the object. In your code, you express properties as enclosed upvalues, which is where the shared state comes from:
function Sword.new(name: string)
local baseProperties = assert(Data:FindFirstChild(name), "Unknown sword type.")
local self = table.clone(require(baseProperties))
self.Combo = 1
self.CanSwing = false
return setmetatable(self, Sword)
end