Hi, I was helping my friend to finish his game, I made a simple auto-firing projectile, but It was so laggy when I tried it in game maybe because It spawns too many projectiles, stressing the remote event, and also It’s not smooth, I don’t know how to fix this because I’m a stupid idiot help me!
Client Script:
local Player = game.Players.LocalPlayer
local Char = Player.Character or Player.CharacterAdded:Wait()
local Mouse = Player:GetMouse()
local ReplicatedStorage = game.ReplicatedStorage
local EventsFolder = ReplicatedStorage.Events
local PewPewEvent = EventsFolder.ShootingEvents.PewPew.PewPew
local StoppedEvent = EventsFolder.ShootingEvents.PewPew.StoppedEvent
local OnCooldown = false
local UIS = game:GetService("UserInputService")
local Debounce = false
local Shooting = false
-- Statistic
local StatsFolder = script.Stats
local Speed = StatsFolder.Speed
local Damage = StatsFolder.Damage
local Cooldown = StatsFolder.Cooldown
UIS.InputBegan:Connect(function(Input)
if Input.KeyCode == Enum.KeyCode.P then
Shooting = true
while Shooting do
task.wait(Cooldown.Value)
PewPewEvent:FireServer(Player)
UIS.InputEnded:Connect(function(Input)
if Input.KeyCode == Enum.KeyCode.P then
Shooting = false
StoppedEvent:FireServer()
end
task.wait()
end)
end
end
end)
Server Script:
local Debris = game.Debris
local ReplicatedStorage = game.ReplicatedStorage
local EventsFolder = ReplicatedStorage.Events
local PewPewEvent = EventsFolder.ShootingEvents.PewPew.PewPew
local StoppedEvent = EventsFolder.ShootingEvents.PewPew.StoppedEvent
local Debounce = false
local ProjectileDeb = false
-- Statistic
local StatsFolder = script.Parent.Stats
local Speed = StatsFolder.Speed
local Damage = StatsFolder.Damage
local Cooldown = StatsFolder.Cooldown
game:GetService("RunService").Heartbeat:Connect(function()
PewPewEvent.OnServerEvent:Connect(function(Player)
local Character = Player.Character
local Humanoid = Character:WaitForChild("Humanoid")
local HRP = Character:WaitForChild("HumanoidRootPart")
Character.Snap:Play()
Character.RapidSnap:Play()
task.wait(0.1)
local Projectile = ReplicatedStorage.Projectiles.PewProjectile:Clone()
Projectile.CFrame = HRP.CFrame * CFrame.new(0, 0, 0)
Projectile.Orientation = Vector3.new(-90, 90, 0)
Projectile.Parent = workspace
local Velocity = Instance.new("BodyVelocity", Projectile)
Velocity.MaxForce = Vector3.new(math.huge, math.huge, math.huge)
Velocity.Velocity = HRP.CFrame.LookVector * Speed.Value
Velocity.P = 3550
Projectile.Touched:Connect(function(Hit)
if Hit.Parent:FindFirstChild("Humanoid") and not Humanoid then
Hit.Parent.Humanoid:TakeDamage(Damage.Value)
Projectile:Destroy()
elseif Hit.Parent:FindFirstChild("ProjectileDestroyer") then
Projectile:Destroy()
end
end)
end)
end)
Set the network owner of each spawned bullet to the user who fired it. This will prevent any other player from handling it’s physics, and so it won’t jitter around when it’s about to reach a different player.
Also, you’re connecting to the remote event every heartbeat on the server. That’s going to rip your game apart!
Instead of creating parts for projectiles on the server, you should do a “raycast simulation” on both the client & server, but the client will have a part visualizing the projectile.
I prefer using a while loop instead of RunService on projectiles because it yields for a function to finish while RunService doesn’t.
One Script & Loop/Heartbeat can handle all the projectiles, you can easily make the code more readable & organized with OOP (Object Oriented Programming);
The reason why projectiles should be rendered on the client is because of client-server replication, when a server creates a part, it moves smoothly on their perspective but on the client is jittery and “laggy”. The solution to this is to just render projectiles on the client.
You can do a raycast simulation using these formulas:
BPosition = BPosition + Direction pos += direction
Direction is where the bullet is facing, while BPosition is the projectile’s position.
By doing the things I explained above, you can achieve the following:
Make sure you ask me any questions if you have any;
I hope you get the idea of what I’m trying to explain, good luck!
This is something I’ve been working on recently and it seems from trying to send every client shot of a fast firing gun over a network.
Instead, you simply have to trust that the client’s shot is accurate. It’s cheatable, but this is the standard in any videogame.
From here, you can choose whether to replicate tracers or not.
My approach is checking every 0.5 seconds if the gun is firing automatic. If it is, propagate a keepalive event to the server with the attachment being shot from and the target position. Any time this keep alive event is active, simulate the effect on clients that should see it.
It works surprisingly well, even in high ping, but I haven’t battle tested it yet.
I’m also using fastcast for what it’s worth!
I dont understand, isnt raycast like a lazer which is instant? How could a lazer be a substitute for a moving projectile? and how could a thin line be substituted for hitbox of a rocket ammo which is massive. Either what I think of raycast is incorrect?
What I heard about raycast was its a line from point A to point B. It is very thin and its instant. Its a line. Is this correct?
Oh alright so how can they be used for projectiles? projectiles have speed but raycasts and blockcasts are instant. I could only see the use if the projectile are like lazers and beam abilities with no speed