The bullets are made on the server, so they take a bit to replicate. This results in them being behind on the client.
One solution is to create the bullets before hand on the server, then give the client network ownership of those bullets, and control the bullets from the client.
Another solution is to have visual-only/“fake” bullets shown on the client, so that the client’s bullets look up to date.
I understand your logic, and I think it should work. But how do I give the right to control the bullets to the client? How can I do this with the script written above?
Create a Model inside the helicopter to store the bullets (if you’re using streaming enabled set it to Persistent)
On the server, when the player gets into a helicopter, create a bunch of bullets for them. Use AlignPositions to hold the bullets far away from anything else. To give the client control of the bullets, use BasePart:SetNetworkOwner(heliPlayer). Add any sort of damage detection you need for the bullets on the server (e.g. touched, raycasting, etc).
On the client, when the player fires bullets, remove the AlignPosition, move the bullets to the helicopter, and set the velocity.
To refill the bullets, either have a required reload time (e.g. the minigun runs out of ammo and send the server a request for a refill), or send the server a remote event each time a bullet is fired for a new bullet to be created and replace the fired one.
You can also add some security to this, just as checking if the bullets are in valid position. (There are some security issues with giving the client control over bullets.)
The other method is to create visualizer bullets on the client, send the physics equations of those bullets to the server (i.e. the initial position, velocity, and initial time), then add real bullets on the server but with the initial position increased by velocity * (server time - initial time) so they match exactly with the client.
When dealing with the Internet and lag, don’t have the bullets spawn exactly in the device, but out in front to account for it. You can even add some distance adjustments for the speed of the helicopter so if it’s stationary, maybe they do spawn in the gun, but when it’s moving, you add those speed distance changes to the spawn distance. With a little tweaking, you can nail it exactly; pretty easily without having to depend on the Clients so much.
I tried to do as you said, but something went wrong, how can I fix it, because LinearVelocity is responsible for the direction and speed of the bullet
Server Scrpt:
coroutine.resume(coroutine.create(function(MGGUN)
wait(15)
while task.wait(0.125) do
local bullet = game.ReplicatedStorage.Bullet:Clone()
bullet.Parent = workspace
bullet:SetNetworkOwner(game.Players.lhacerl228)
game:GetService("Debris"):AddItem(bullet, 15)
game.ReplicatedStorage.Test:FireClient(game.Players.lhacerl228, bullet)
end
end))
Local Script:
game.ReplicatedStorage.Test.OnClientEvent:Connect(function(bullet)
coroutine.resume(coroutine.create(function()
while task.wait(0.125) do
bullet.CFrame = workspace.BulletFire.CFrame
game:GetService("Debris"):AddItem(bullet, 15)
bullet.LinearVelocity.VectorVelocity = workspace.BulletFire.CFrame.LookVector * 1000
end
end))
end)
Error:
LinearVelocity is not a valid member of Part "Bullet" - Studio
coroutine.resume(coroutine.create(function(MGGUN)
wait(15)
while task.wait(0.125) do
local bullet = game.ReplicatedStorage.Bullet:Clone()
bullet.Parent = workspace
bullet:SetNetworkOwner(game.Players.lhacerl228)
game.ReplicatedStorage.Test:FireClient(game.Players.lhacerl228, bullet)
end
end))
Instead of firing to the heliplayer, fire to all clients:
coroutine.resume(coroutine.create(function(MGGUN)
wait(15)
while task.wait(0.125) do
local bullet = game.ReplicatedStorage.Bullet:Clone()
bullet.Parent = workspace
bullet:SetNetworkOwner(game.Players.lhacerl228)
game.ReplicatedStorage.Test:FireAllClients(bullet)
end
end))
Pilot: bullet fly there then
Passenger client: bullet fly there then
And it goes out of sync
I have an idea and it works. Start releasing bullets for all clients in StarterPlayerScript. But this is only a visualization, it’s possible that the clock may be out of sync and how to deal damage so that a player with poor internet or a cheater cannot gain an advantage
I figured out how to do it this way. And when hit, send a RemoteEvent about the coordinates, if there is a Humanoid at the coordinates, then cause damage to it
Server Script:
coroutine.resume(coroutine.create(function(MGGUN)
wait(15)
while task.wait(0.125) do
game.ReplicatedStorage.Test:FireAllClients()
end
end))
Each object has a linear velocity reading, so you could read the velocity of the Helicopter and simply add it to the velocity of the bullet. It looks like you already have it coded to fire at a velocity of +1000, so other than making realistic momentum carry, the work would probably have to be done on the CFrame instead. You might trying delaying the CFrame teleport until after the velocity change.
Right now, your bullets work like this
Clone Bullet
Teleport to starting position via CFrame
Apply Linear Velocity
Try instead
Clone Bullet
Apply Linear Velocity
Teleport to starting position via CFrame
This way, the bullet is already “moving” before the teleport instead of being “stationary” and then moving, which because of Internet lag, makes it seem to fire with a delay. You might need to wait a server frame or two to get the timing down to appear like they always fire from the gun and not behind the gun.
Also, depending on how much “firing” is going on, you might consider a system of recycling bullets instead of cloning them because object creation is a loooooot slower than object recycling when it comes to physics projectiles.
I created a script for bullets on the client and when necessary I sent a message from the server to the client that it was time to fire the bullets, and when they hit the target I sent a request to the server to cause damage