What do you want to achieve? Keep it simple and clear!
I want to have a gun that can maintain very high rates of fire of up to 1/600 a second seamlessly.
What is the issue? Include screenshots / videos if possible!
I have a gun that has a very high rate of fire and every time I try to fire my weapon at lets say 1/600 a second or even down to 1/50 a second there’s a lot of bullets that just pool up at the muzzle which causes some problems for me whether it be performance or they destroy each other for apparent reason despite being whitelisted to not destroy other bullets.
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
I’m not sure how to solve this problem. I’m not sure if its an engine limitation or anything because im pretty sure even phantom forces are able to seamlessly instantiate bullets and have them fire at very high rates.
This is my code for instantiating the bullet
GunFired.OnServerEvent:Connect(function(player,ammo30,bullet30,Spawn30)
if ammo30 > 0 then
local bullet = bullet30:Clone()
local bv = Instance.new("BodyVelocity")
bullet.CFrame = Spawn30.CFrame
bullet.Parent = workspace
bv.Parent = bullet
bv.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
bv.Velocity = Spawn30.CFrame.LookVector * 700
ammo30 -= 1
GunFired:FireAllClients(ammo30)
end
end)
This is the bullet script that is responsible for self destruction and hit detection
local bullet = script.Parent
local now = tick()
--print("Bullet instantiated")
game:GetService("Debris"):AddItem(bullet,5)
bullet.Touched:Connect(function(hit)
print("Hit something "..hit.Name)
if hit.Parent:FindFirstChild("Humanoid") then
print("Hit someone")
local humanoid = hit.Parent.Humanoid
humanoid.Health -= 10
bullet:Destroy()
else
print("Hit something else "..hit.Name)
if (hit.Name == "Bullet30" or hit.Name == "Bullet120") then
--print("Hit something that wasnt a bullet")
--bullet:Destroy()
return
end
bullet:Destroy()
end
end)
the thing is, i’m pretty sure phantom forces does not use body movers. they move it all with cframes. which means they don’t use roblox’s physics engine at all
what you can do is maybe have the effects run on clients only and have the server tell every client to do the same thing, or just do what phantom forces does and step away from roblox’s physics engine and handle everything yourself.
I’m not exactly sure why this is happening, but it could be due to the bullets having CanCollide true, it could also be a completely unexpected and random issue with Roblox, I’m honestly not too sure.
Also, just a heads up but you shouldn’t Parent any of your instances until you’ve set their properties and added their children, this could also be an issue.
Try this code:
local bullet30 = ... -- You shouldn't be passing instances through remotes
-- They take up a lot of bandwidth that way, just make a default bullet here and clone it.
GunFired.OnServerEvent:Connect(function(player,ammo30,Spawn30)
if ammo30 > 0 then
-- Likely don't need this task.spawn wrapper here
-- but it could solve some issues, so we'll try it.
task.spawn(function()
local bullet = bullet30:Clone()
local bv = Instance.new("BodyVelocity")
bullet.CFrame = Spawn30.CFrame
bv.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
bv.Velocity = Spawn30.CFrame.LookVector * 700
bv.Parent = bullet
bullet.Parent = workspace
end)
ammo30 -= 1
GunFired:FireClient(Player, ammo30)
-- No need to FireAllClients for one persons ammo.
end
end)
And @MysteryOfHyper is correct, PF doesn’t use BodyMovers, in fact I believe they use a form of FastCast and raycast their bullets in increments to simulate their Muzzle Velocity.
im thinking its the physics engine getting overwhelmed. whenever theres lots of simulated objects everything slows down and since they are firing 600+ bullets every second or more, roblox simply cant keep up.
Using task spawner made performance x100 worse and looks like making the bullet get instantiated by the server made it worse too
local ReplicatedStorage = game:WaitForChild("ReplicatedStorage")
local GunFired = ReplicatedStorage.TSFWeapons.ServerEvents.GunFired
local MoveArm = ReplicatedStorage.TSFWeapons.ServerEvents.MoveArm
local bullet = ReplicatedStorage.TSFWeapons.Bullet30:Clone()
GunFired.OnServerEvent:Connect(function(player,ammo30,Spawn30)
GunFired.OnServerEvent:Connect(function(player,ammo30,Spawn30)
if ammo30 > 0 then
-- Likely don't need this task.spawn wrapper here
-- but it could solve some issues, so we'll try it.
--task.spawn(function()
local bullet = bullet:Clone()
local bv = Instance.new("BodyVelocity")
bullet.CFrame = Spawn30.CFrame
bv.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
bv.Velocity = Spawn30.CFrame.LookVector * 700
bv.Parent = bullet
bullet.Parent = workspace
--end)
ammo30 -= 1
GunFired:FireClient(player, ammo30)
-- No need to FireAllClients for one persons ammo.
end
end)
end)
Amended code but still having the bullet instantiated by the server made performance unacceptable
I forgot to got rid of the second clone and the performance is better however the bullet doesnt seem to work properly anymore. The offsets are strange and even direction is completely wrong.
and after using it for a while I get this error
The Parent property of Bullet30 is locked, current parent: NULL, new parent Workspace - Server - GunHandler:16
local bullet = ReplicatedStorage.TSFWeapons.Bullet30:Clone()
GunFired.OnServerEvent:Connect(function(player,ammo30,Spawn30)
GunFired.OnServerEvent:Connect(function(player,ammo30,Spawn30)
if ammo30 > 0 then
-- Likely don't need this task.spawn wrapper here
-- but it could solve some issues, so we'll try it.
task.spawn(function()
--local bullet = bullet:Clone()
local bv = Instance.new("BodyVelocity")
bullet.Parent = workspace
bullet.CFrame = Spawn30.CFrame
bv.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
bv.Velocity = Spawn30.CFrame.LookVector * 700
bv.Parent = bullet
end)
ammo30 -= 1
GunFired:FireClient(player, ammo30)
-- No need to FireAllClients for one persons ammo.
end
end)
end)
I think Ill switch over to fastcast, I just tried out the debug gun, it was very impressive
No no, you do need to clone that, get rid of the task.spawn–
Nevermind I’ll just do it for you really quickly since that’s the easiest way to make it as I’m trying to explain.
oh my god.
local bullet = ReplicatedStorage.TSFWeapons.Bullet30
-- I was referring to the clone up here.
-- how the hell did you get another OnServerEvent wrapper????????
-- this is why the performance was going downhill fast
--GunFired.OnServerEvent:Connect(function(player,ammo30,Spawn30)
GunFired.OnServerEvent:Connect(function(player,ammo30,Spawn30)
if ammo30 > 0 then
local _bullet = bullet:Clone()
local bv = Instance.new("BodyVelocity")
_bullet.Parent = workspace
_bullet.CFrame = Spawn30.CFrame
bv.MaxForce = Vector3.new(math.huge,math.huge,math.huge)
bv.Velocity = Spawn30.CFrame.LookVector * 700
bv.Parent = _bullet
ammo30 -= 1
GunFired:FireClient(player, ammo30)
-- No need to FireAllClients for one persons ammo.
end
end)
--end)
Edit:
Elaborating on what you did wrong:
You wrapped GunFire.OnServerEvent:Connect() in another GunFire.OnServerEvent:Connect() call, which meant every single time you called it, you ended up making another connection that would ALSO be executed when you called FireServer from the client. So after a couple goes, you’re making like 20 bullets instead of 1.
Yeah it works better, not sure if there was a difference between having the task spawner there or not but its more or less back to square 1 just simply more efficient with remote events I suppose… by the way is there any like “How to use Fast Cast” tutorial out there? I dont exactly learn the best way simply from documentation…
Fast cast looks like the only viable way forward at this point and I was always wondering if there was an easier way to achieve what I am doing. I always strive for efficiency in my code so everyone can enjoy sweet 60FPS.