Smooth and Non-laggy Projectile

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)
2 Likes

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!

3 Likes

About the heartbeat function, what’s your suggestion?

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);

You can learn OOP here: https://devforum.roblox.com/t/an-in-depth-look-at-oop-roblox-lua/1049827

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!

2 Likes

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!

1 Like

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?

1 Like

You can easily replace :Raycast() with :Blockcast().
Edit: And yes, you are correct, raycasts are thin lines.

Oh alright but Blockcast() is also instant no? does it have a adjustable speed for like slow moving projectile hit detection?

1 Like

Yes Blockcast is also instant, it acts the same as raycasts

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

1 Like

Hello? so I assume raycasts shouldnt be used for projectiles that arent instant?

1 Like