What do you want to achieve?
Hello, I’ve been working the entire day on client sided projectiles, since they’re smoother and put less strain on the server.
My main issue is that the current system is very vulnerable to exploiters, and sometimes not accurate.
It works like this:
Server side
local bullet = flameFolder["Gun Bullet"]:Clone()
bullet.Anchored = true
bullet.Position = model.Gun["Tip Attachment"].WorldPosition
bullet.Parent = workspace.Effects
game.Debris:AddItem(bullet, 1.5)
local mouseInfo = game.ReplicatedStorage.Relations.GetMouseInfoRemoteFunction:InvokeClient(Player)
bullet.CFrame = CFrame.new(bullet.Position, mouseInfo.Hit.p)
local DetectionArguments = {}
DetectionArguments.Speed = 200
DetectionArguments.Character = Player.Character
local Arguments = {}
Arguments.Player = Player
Arguments.MouseHit = mouseInfo.Hit
local finalPosition = detection.ClientSideProjectile(bullet, Arguments, DetectionArguments)
repeat wait() until finalPosition if not finalPosition then return end
The detection.ClientSideProjectile function, still on the server:
function detection.ClientSideProjectile(Projectile, Arguments, DetectionArguments)
local returnValue = nil
local clientsAnswers = {}
local projectilePosition = Projectile.Position
DetectionArguments.Part = Projectile
local PlayersFiredTo = game.Players:GetPlayers()
for _,v in pairs(PlayersFiredTo) do
spawn(function()
local returningValue
returningValue = clientFunctions:InvokeClient(v, "ProjectileFire", DetectionArguments)
table.insert(clientsAnswers, returningValue)
end)
end
Then, it compares every position recieved from the clients it reached to determine which one would be the most accurate, but this won’t work if the player is alone on the server, since it would have nothing to compare the position recieved to.
At the end, I use raycast to detect if the part did actually go in a straight line, the way it’s intended:
--//ProjectilePosition refers to the position the projectile first had before sending it to clients
local rayInfo = RaycastParams.new()
rayInfo.FilterType = Enum.RaycastFilterType.Whitelist
rayInfo.FilterDescendantsInstances = {bullet}
local distance = (projectilePosition - returnValue).Magnitude
if not Arguments.Velocity then
ray = workspace:Raycast(projectilePosition, Projectile.CFrame.lookVector*distance, rayInfo)
else
ray = workspace:Raycast(projectilePosition, Arguments.Velocity*distance, rayInfo)
end
if ray then
return returnValue
else
print("Object not found")
return nil
end
The raycast at the end does work most of the time, but I don’t know how to make it always successful.