Best way to make server-sided first person raycasting

So, I’m making a new gun system for the third time, and I want to make raycasting server sided.


My problem?
I’m not sure how to properly set the position of the raycast origin on the server.

Setting it to the head of the player could work, but would be offset by the players ping, making wall peeking impossible or incredibly annoying.

But, if I send the cameras CFrame over to the server, exploiters would be able to send their own CFrames to hack and shoot people anywhere on the map.

So because of that, I’m just not sure on how to do this.


My code:

Events.FireGun.OnServerEvent:Connect(function(Player, CameraLookVector)
	local RayOrigin = nil -- what do i put here how do i do this help
	local RayDirection = CameraLookVector * 500
	local RayParams = RaycastParams.new()
	RayParams.FilterDescendantsInstances = {Player.Character}
	local Raycast = workspace:Raycast(RayOrigin, RayDirection, RayParams)
	if Raycast and Raycast.Instance and Raycast.Instance.Parent:FindFirstChild('Humanoid') then
		-- rest of code here when i script it
	end
end)

Not asking for code, asking for solutions.

If anyone gets confused, I do know how to raycast, its just first-person server sided raycasting that I’m struggling with.

I am also not using tools, so yeah there’s that.

1 Like

Sending local player camera cframe would work just fine.
Just remember to implement a sanity check and don’t raycast if the magnitude between the caster’s head and the position sent to the server is greater than 5 or so.

this will cause performance drops you should leave the raycasting to the client and just confirm hits on the server

1 Like

That’s a previous system I used, but I got a friend to make hacks for it and well… It only took them around 30 minutes to get hacks that allowed the user to kill anyone at any time.

So that’s why I specifically want server side raycasting.

Again, hackers would be able to modify the cframe value being sent through and allow them to shoot people through walls.

I believe I made a system like this once before that kicked the player if the check failed, but I would always get kicked upon shooting.

Might try it again later, will post if it worked or not!

there is a way to stop this, every popular game with guns use the client for raycasting

but if you want it on the server just some warnings

  1. there is always gonna be lag between the shot and the bullet appearing. since latency exists its always going to appear as its falling behind

  2. a lot of these guns will cause the server to lag. the server only runs at 60 fps and cannot handle a lot of remote events/data being sent to it at once

3 Likes

Again, it is very easy to exploit the local side of things which is specifically why I want to make this server sided.

I could just optimize the entire game by doing client raycasts, and only fire events to the server when the player hits an enemy.

Plus, on one of my older gun games which had a very unoptimized client and server raycast system, the game ran perfectly fine when there were 5 people in the game all shooting eachother.
(5 People is all I ever got to test on it)

For each bullet fired on that game, there was about 3 events being fired, and one containing over 10 variables being sent over through a table.

But as for ways to stop the exploits, can you explain some ways on how I can? I would much prefer have client raycasting as its a lot better feeling, but I cant pull it off myself without having the game be very easily exploitable.

Upon further testing, this is a bad solution.

With 20 ping, simply falling causes 7 stud gaps between the head and the camera, and a 2 to 3 stud gap when walking.

The camera CFrame being sent through though does feel good to use, so I would like to use it but making it secure is proving to be difficult.

1 Like

Send Raycast from Client to Server. Then Raycast again in Server based off of the raycast from the Client. If something is off, then it’s exploited.

The whole problem with that is that that’s very easily exploitable which is why I won’t do that, plus I’ve already done it once before.

The problem I’m having is that anything I can think of is easily exploitable, and I want to get a good workaround for it.

Again, you gotta remember, hackers can just send fake values from the client to the server, which would make them be able to shoot people through walls using that raycasting method, which obviously just ruins the fun for everyone.

yes, thats why you sanity check this, as the other posted said, a magnitude under or equal to 5 (depends on type of game if player is fast, increase magnitude) for the head, also raycast between head and client cframe to verify they arent trying to shoot through a wall yea?

laggy players may see hit reg issues due to this but :person_shrugging: we gotta do what we gotta do

2 Likes

Will do this, but the magnitude checks didn’t work at all, with 20 ping.

Will go rescript my system, will reply again with the results.

Update: got a good system working I think.

Server hit verification:

	local TestRay = workspace:Raycast(ClientCast.Position, CFrame.lookAt(ClientCast.Position, Player.Character.Head.Position).LookVector * 10000, VerifyParams)
	
	if not TestRay or not TestRay.Instance:IsDescendantOf(Player.Character) then print('error2') return end
	
	local TestRay2 = workspace:Raycast(Player.Character.HumanoidRootPart.Position, CFrame.lookAt(ClientPos, Player.Character.HumanoidRootPart.Position).LookVector * 10000, VerifyParams)

	if TestRay2 and (TestRay2.Position - Player.Character.HumanoidRootPart.Position).Magnitude > 10 then print('error3') return end

Тhis is so untrue.
The raycasting in Roblox is very inexpensive and the server can easily handle 10 - 50 raycasts per frame (depending on the ray length and count of filtered objects).
You can also further optimize it by using parallel Lua features.

This is one of the best solutions you can use.
To compensate the player speed, increase the magnitude if the player’s character is moving.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.