Hello, I’m trying to improve my FastCast gun system for my mecha game but my concern is that ping and client-server communication is somewhat unsatisfactory. I want to be able have very performant client-server communication for the code that would allow up to at least 12 simultaneous players each holding at least 2-4 weapons at the same time.
I have considered offloading networking to player rather than the server but I’m not sure how effective that would be and I’m not sure how to do it myself.
One important thing to note is that performance in studio is very satisfactory however performance on live server is unsatisfactory as ping skyrockets.
I want be able to have an absolute metric ton of “projectiles” at anyone time as a sort of factor of safety for what the game should be able to handle at minimum ping.
This code handles the client
local UIS = game:GetService("UserInputService")
local RS = game:GetService("ReplicatedStorage")
local RunS = game:GetService("RunService")
local Gun = script.Parent
local player = game:GetService("Players").LocalPlayer
local mouse = player:GetMouse()
--local Ammo30mm = script.Parent:GetAttribute("PriAmmo")
--local Ammo120mm = script.Parent:GetAttribute("AltAmmo")
local heldFire = false
local lastFire = 0
local fireEvent = Gun:WaitForChild("GunFire")
local Attributes = Gun:GetAttributes()
local HUD = player.PlayerGui.TSFHUD
local function fire()
local now = tick()
--print("Fired function")
local mousePos = mouse.Hit.Position
if Gun:GetAttribute("Mode") == "Pri" and ((Gun:GetAttribute("Hardpoint") == "LH") or (Gun:GetAttribute("Hardpoint") == "RH")) then
--print(tick() - now)
if now - lastFire >= .01 then
--print("Fired Pri")
lastFire = now
if Attributes["PriAmmo"] > 0 then
fireEvent:FireServer(mousePos)
Attributes["PriAmmo"] -= 1
if Attributes["Hardpoint"] == "LH" then
HUD.ARML.AMMO.Text = Attributes["PriAmmo"]
elseif Attributes["Hardpoint"] == "RH" then
HUD.ARMR.AMMO.Text = Attributes["PriAmmo"]
end
end
end
elseif Gun:GetAttribute("Mode") == "Alt" and ((Gun:GetAttribute("Hardpoint") == "LH") or (Gun:GetAttribute("Hardpoint") == "RH")) then
if now - lastFire >= 1 then
--print("Fired Alt")
lastFire = now
if Attributes["AltAmmo"] > 0 then
fireEvent:FireServer(mousePos)
Attributes["AltAmmo"] -= 1
if Attributes["Hardpoint"] == "LH" then
HUD.ARML.AMMO.Text = Attributes["AltAmmo"]
elseif Attributes["Hardpoint"] == "RH" then
HUD.ARMR.AMMO.Text = Attributes["AltAmmo"]
end
end
end
end
end
RunS.RenderStepped:Connect(function()
if heldFire then
fire()
end
end)
UIS.InputBegan:Connect(function(i,gp)
if not gp and i.UserInputType == Enum.UserInputType.MouseButton1 then
heldFire = true
end
end)
UIS.InputEnded:Connect(function(i,gp)
if not gp and i.UserInputType == Enum.UserInputType.MouseButton1 then
heldFire = false
end
end)
Gun.Equipped:Connect(function()
if Attributes["Hardpoint"] == "LH" then
HUD.ARML.NAME.Text = Attributes["DisplayName"]
if Attributes["Mode"] == "Pri" then
HUD.ARML.AMMO.Text = Attributes["PriAmmo"]
HUD.ARML.MODE.FIREMODE.Text = Attributes["PriAmmoType"]
elseif Attributes["Mode"] == "Alt" then
HUD.ARML.AMMO.Text = Attributes["AltAmmo"]
HUD.ARML.MODE.FIREMODE.Text = Attributes["AltAmmoType"]
end
elseif Attributes["Hardpoint"] == "RH" then
HUD.ARMR.NAME.Text = Attributes["DisplayName"]
if Attributes["Mode"] == "Pri" then
HUD.ARMR.AMMO.Text = Attributes["PriAmmo"]
HUD.ARMR.MODE.FIREMODE.Text = Attributes["PriAmmoType"]
elseif Attributes["Mode"] == "Alt" then
HUD.ARMR.AMMO.Text = Attributes["AltAmmo"]
HUD.ARMR.MODE.FIREMODE.Text = Attributes["AltAmmoType"]
end
elseif Attributes["Hardpoint"] == "LP" then
HUD.PYLONL.NAME.Text = Attributes["DisplayName"]
if Attributes["Mode"] == "Pri" then
HUD.PYLONL.AMMO.Text = Attributes["PriAmmo"]
HUD.PYLONL.MODE.FIREMODE.Text = Attributes["PriAmmoType"]
elseif Attributes["Mode"] == "Alt" then
HUD.PYLONL.AMMO.Text = Attributes["AltAmmo"]
HUD.PYLONL.MODE.FIREMODE.Text = Attributes["AltAmmoType"]
end
elseif Attributes["Hardpoint"] == "RP" then
HUD.PYLONR.NAME.Text = Attributes["DisplayName"]
if Attributes["Mode"] == "Pri" then
HUD.PYLONR.AMMO.Text = Attributes["PriAmmo"]
HUD.PYLONR.MODE.FIREMODE.Text = Attributes["PriAmmoType"]
elseif Attributes["Mode"] == "Alt" then
HUD.PYLONR.AMMO.Text = Attributes["AltAmmo"]
HUD.PYLONR.MODE.FIREMODE.Text = Attributes["AltAmmoType"]
end
end
end)
This code handles the server
local RS = game:GetService("ReplicatedStorage")
local FireEvent = script.Parent:WaitForChild("GunFire")
local Debris = game:GetService("Debris")
local Gun = script.Parent
local FirePoint30 = Gun.GWS9.FirePoint30
local FirePoint120 = Gun.GWS9.FirePoint120
local Attributes = Gun:GetAttributes()
local RNG = Random.new()
local TAU = math.pi*2
local FastCast = require(Gun.FastCastRedux)
local PartCache = require(Gun.PartCache)
local bulletsFolder = workspace.Bullets
local bullet30 = bulletsFolder.Bullet30
local bullet120 = bulletsFolder.Bullet120
local Caster = FastCast.new()
local MaxRange = 2000
local CastParams = RaycastParams.new()
CastParams.FilterType = Enum.RaycastFilterType.Blacklist
CastParams.IgnoreWater = true
local BulletCache = PartCache.new(bullet30, 50, bulletsFolder)
local CastBehaviour = FastCast.newBehavior()
CastBehaviour.RaycastParams = CastParams
CastBehaviour.Acceleration = Vector3.new(0,-workspace.Gravity,0)
CastBehaviour.AutoIgnoreContainer = true
CastBehaviour.HighFidelityBehavior = FastCast.HighFidelityBehavior.Default
CastBehaviour.MaxDistance = MaxRange
CastBehaviour.CosmeticBulletContainer = bulletsFolder
CastBehaviour.CosmeticBulletProvider = BulletCache
local impactParticles = bulletsFolder.EffectPart.Effect:GetChildren()
local function makeFX(position,normal)
local attachment = Instance.new("Attachment")
attachment.CFrame = CFrame.new(position,position+normal)
attachment.Parent = workspace.Terrain
for i,v in pairs(impactParticles) do
local particle = v:Clone()
particle.Parent = attachment
Debris:AddItem(attachment,particle.Lifetime.Max )
end
end
local function onRayHit(cast,result,velocity,bullet)
local hit = result.Instance
local hitPoint = result.Position
local normal = result.Normal
local character = hit:FindFirstAncestorWhichIsA("Model")
if character and character:FindFirstChild("Humanoid") then
character.Humanoid:TakeDamage(10)
end
--makeFX(hitPoint,normal)
end
local function onRayTerminated(cast)
local cosmeticBullet = cast.RayInfo.CosmeticBulletObject
if cosmeticBullet ~= nil then
if CastBehaviour.CosmeticBulletProvider ~= nil then
CastBehaviour.CosmeticBulletProvider:ReturnPart(cosmeticBullet)
else
cosmeticBullet:Destroy()
end
end
end
local function onLengthChanged(cast,lastPoint,direction,length,velocity,bullet)
if bullet then
local bulletLength = bullet.Size.Z/2
local offset = CFrame.new(0,0, -(length - bulletLength))
bullet.CFrame = CFrame.lookAt(lastPoint,lastPoint+direction):ToWorldSpace(offset)
end
end
local function firePrimary(mousePos)
local origin = FirePoint30.WorldPosition
local direction = (mousePos - origin).Unit
local directionalCF = CFrame.new(Vector3.new(),direction)
local direction = (directionalCF * CFrame.fromOrientation(0,0,RNG:NextNumber(0,TAU))* CFrame.fromOrientation(math.rad(RNG:NextNumber(Attributes["PriMinSpread"],Attributes["PriMaxSpread"])),0,0)).LookVector
local modifiedBulletSpeed = direction*1000
Caster:Fire(origin,direction,modifiedBulletSpeed,CastBehaviour)
end
local function fireAlt()
end
FireEvent.OnServerEvent:Connect(function(Player,MousePos)
if Attributes["Mode"] == "Pri" then
firePrimary(MousePos)
elseif Attributes["Mode"] == "Alt" then
fireAlt()
end
end)
Caster.LengthChanged:Connect(onLengthChanged)
Caster.RayHit:Connect(onRayHit)
Caster.CastTerminating:Connect(onRayTerminated)
Gun.Equipped:Connect(function()
CastParams.FilterDescendantsInstances = {Gun.Parent, bulletsFolder}
end)
The code is mainly taken away from the main fastcast debug gun but something just doesnt seem right with the high ping.
I have a file ready to give away if anyone needs it but right now I want to see what can be done before having to resort to that.
Thanks in advance.