The weird behavior is due to the fact you still use the server. In this scenario, we are only using the server to transport information from one client to all clients. If you replicate a :Clone()
on all clients, it will behave the same as if it were on the server, since all clients get their own clone, thus making everyone see a ball.
To correct your scripts, I made some slight changes. Most importantly, how you log your calculations in the RemoteEvent
, and how the client should receive said information.
The code starts in a LocalScript
:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local fireball = ReplicatedStorage.Fireball
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
if input.KeyCode == Enum.KeyCode.E then --//Or any other way of how the fireball is triggered
local fireballCFrame = humanoidRootPart.CFrame * CFrame.new(1.25, 0, -2.5)
ReplicatedStorage.SendInfoToServer:FireServer(fireballCFrame)
--//print("Sent remote to server.")
end
end)
This first function has handled the calculating of the CFrame belonging to the player, which
means it is now the value of the player’s position, no matter whose client it reads.
You then receive said CFrame on the server and pass it through all the clients with the following script:
local ReplicatedStorage = game:GetService("ReplicatedStorage")
ReplicatedStorage.SendInfoToServer.OnServerEvent:Connect(function(player, fireballCFrame, fireballOrientation)
ReplicatedStorage.ShowFireball:FireAllClients(fireballCFrame)
end)
Now it will send back the CFrame of the fireball to all the clients, including of the person who fired the fireball. Response time is still in the milliseconds, so delay will not be noticeable for the player firing the ball.
Receive the new RemoteEvent
in the same LocalScript
as the first function. This will then proceed to use the passed down information and calculate the fireball’s CFrame
and Velocity
. Again, it will do this on all clients, so everyone will see the same (with some having just a few milliseconds difference). That happens in this function:
ReplicatedStorage.ShowFireball.OnClientEvent:Connect(function(fireballCFrame)
--//print("Clients received task.")
local newBall = fireball:Clone()
newBall.Parent = workspace
newBall.CFrame = fireballCFrame
local Velocity = Instance.new("BodyVelocity")
Velocity.maxForce = Vector3.new(math.huge, math.huge, math.huge)
Velocity.Velocity = newBall.CFrame.lookVector * 30
Velocity.Parent = newBall
task.delay(3, function()
newBall:Destroy() --//Keep it tidy
end)
end)
TL;DR:
LocalScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
local fireball = ReplicatedStorage.Fireball
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local humanoidRootPart = character:WaitForChild("HumanoidRootPart")
UserInputService.InputBegan:Connect(function(input, gameProcessedEvent)
if input.KeyCode == Enum.KeyCode.E then
local fireballCFrame = humanoidRootPart.CFrame * CFrame.new(1.25, 0, -2.5)
ReplicatedStorage.SendInfoToServer:FireServer(fireballCFrame)
--//print("Sent remote to server.")
end
end)
ReplicatedStorage.ShowFireball.OnClientEvent:Connect(function(fireballCFrame)
--//print("Clients received task.")
local newBall = fireball:Clone()
newBall.Parent = workspace
newBall.CFrame = fireballCFrame
local Velocity = Instance.new("BodyVelocity")
Velocity.maxForce = Vector3.new(math.huge, math.huge, math.huge)
Velocity.Velocity = newBall.CFrame.lookVector * 30
Velocity.Parent = newBall
task.delay(3, function()
newBall:Destroy()
end)
end)
ServerScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
ReplicatedStorage.SendInfoToServer.OnServerEvent:Connect(function(player, fireballCFrame, fireballOrientation)
ReplicatedStorage.ShowFireball:FireAllClients(fireballCFrame)
end)