Shoot projectile on client/ server does not work well

  1. What do you want to achieve?
    Hello guys, I want to make a smooth projectile with good security.
  2. What is the issue?
    It is always a trade-off, no matter what I do. if I calculate HumanoidRootPart.CFrame.LookVector on the server, if I turn too fast, the projectile is delayed
    if I calculate HumanoidRootPart.CFrame.LookVector on the client and send it to server, the projectile works perfectly, but hacker can tamper with values client send to server
  3. What solutions have you tried so far?
		elseif action == "RButton" then
			warn("RRRRR")
			local hitDirection, projectileCFrame = fireProjectile(player)
			remoteEvent:FireServer("PressR", tool,hitDirection, projectileCFrame)
		end

function fireProjectile(player1)
	local character = player1.Character
	local hitDirection =  character.HumanoidRootPart.CFrame.LookVector

	local projectile = ReplicatedStorage.SwordSlashEffect:Clone()
	projectile.CFrame = character.HumanoidRootPart.CFrame * CFrame.new(Vector3.new(0, 1, -5))   -- Set the position to the handle of the tool


	projectile.Anchored = true -- we need projectile anchord, so it wont drop down when we change its cframe
	projectile.Parent = game.Workspace

	local connectionVFX
	connectionVFX = RunService.Heartbeat:Connect(function(deltaTime)
		if projectile ~= nil then
			projectile.Position = projectile.Position + hitDirection
		else -- if the projectile is destroyed, disconnect our connection!
			connectionVFX:Disconnect()
		end
	end)
	------------------------------------------
	--clean up
	--task.wait(0.5)
	--projectile:Destroy()
	return hitDirection,  projectile.CFrame

end

You cant have a smooth projectile and also have good security you even said it yourself,

wait, is that real? I only said that based on my own experience. I saw rellsea and other games combat. they look pretty clean. The only thing I can think of is that they do projectile stuff on clients and somehow send position and direction on the server or hit detection,

Yeah, not sure what those games do but if its a huge headache for you maybe try using a popular module for projectiles

or maybe this

What you can do is send the clients lookVector to the server when the client shoots, and verify that it looks real on the server. After that, you handle the hit detection on the server, but send all the necessary information to the clients so that they can handle the visual aspects. Thus you get serverside hit detection and everything else that actually matters, as well as instant feedback for the client shooting because you can let them render the shot on the client without waiting for the server.

I tried to verify lookVector , but I could not find a way to do it because if the player turn too fast, lookVector on the client will be different from lookVector on server. The only thing i thought of is to check if vectors are close to each other which does not feel practical.

Well honestly you don’t have to care too much about the lookvector unless there’s an actual limit to how fast clients are allowed to turn in your game. As long as its a possible lookvector, then its fine yes?

yea, the thing im worrying about is hackers can send different vectors rather than lookVector which can cause serious problems.

What problem would this cause for you? You only need the lookvector for the direction of the projectile.

so instead of using playerA’s lookVector, hacker can change it to playerB’s lookVector and projectile will fireoff playerB rather than playerA

Right, so thats just a bad implementation yet. The lookVector should just be a unit vector that you times by the projectile movement speed. And the projectile should fire from the humanoidrootpart, not the humanoidrootparts lookvector.

i know about fastcast, but never used it before(it seems for lagging and hitbox stuff). SecureCast, well i am cautious about githup thing as there has been news people putting malicious code in the package.

1 Like

the thing is i send 2 things: hitDirection and projectile.CFrame. projectile.CFrame is for spawning location and hitDirection is for projectile movement. i need those for server to simulate projectile for hitboxes

To reiterate, here’s pretty much exactly what you should do.

When the client wants to fire a projectile, you send the clients lookvector to the server. The client at the same time, starts rendering the visual part of the projectile. It does this without caring about the server, it only does its own local sanity checks on the client to make sure it can fire.

The client shoots the visual projectile forward, and when it hits something, it shows whatever hit effects should show. But nothing beyond that changes.

The server gets the lookVector, does its sanity checks on whether the client can fire, and if it can, iit sends all the projectile information to all the other clients so they can also render a visual projectile. At the same time, it starts a non visual projectile which is purely for the server. With this, it does what actually matters and fires the projectile forward, and when hitting something, it applies whatever game-related changes should happen. E.g people take damage and such.

This way, people mostly won’t ever notice the delays because to them, the projectile appeared from where the humanoidRootPart was, it shot forward instantly, yadayadayada. But the visual indicator that they see, is not the actual projectile, its just a visual version of the projectile. The actual projectile, which may not be synced to the visual one, is fired on the server.

Its pretty much how any well-made FPS in the entire world works. Except they also often have some lag interpolation, rollback, etc. And serverside movement of course.

the thing is i send 2 things: hitDirection and projectile.CFrame. projectile.CFrame is for spawning location and hitDirection is for projectile movement. i need those for server to simulate projectile for hitboxes

You shouldnt need to do that

But the thing is you can never stop ppl from aimbotting right?

Yes pretty much impossible, and no game has ever solved this. People can always manipulate where theyre looking somehow, just like the player can move their mouse to manipulate where theyre looking. The only thing that sort of works well enough, is AI detecting unnatural view angle changes which is pretty much out of scope for most roblox games. Even that is far from perfect. Theres other stopgaps too, but in the end all of them are just that, stopgaps.

this is similar to my approach. i have nonvisual projectile on server and fireallclient() to shoot a visual projectile. “The server gets the lookVector, and does its sanity checks on whether the client can fire” this is part i don’t know how to do it. how would we check its sanity

yea it is impossible even with a big company like Riot with Valorant. they do have Vanguard tho. So, i hope roblox anti-cheat can help us moree(it is already good)

bruh this is way too difficult to even think about

Right, again, you dont need to sanity check the lookvector. Just check if its a vector, and then get the unit vector of that vector on the server(In case the player fiddled with it) because then it’ll always be fine.

You then fire the projectile from the players humanoidRootPart or wherever else, at the position it currently is on the server. Even though they’re likely not the same as the place the client was at the time of firing.

As for the sanity checks on whether the client can fire, I was referring to regular stuff like, does the client have a gun, does the client have that gun, does the client have ammo, has the time for the firing delay passed, etc.