So I’m trying to make a horror game, in which a core mechanic would be the flashlight. What I am trying to achieve is making a flashlight hitbox that detects every part that it touches.
My first tought was to make a ball, then make a raycast result from my camera to the cursor, and then set the ball’s cframe to the raycast result position.
The problem is that, because I can only make this on a local script, the part only moves locally. So when I use the .Touched event on the part, the part only registers collisions with me.
And now my big question is, how would i make that hitbox move on the server, not just locally?
Here’s my script
wait(1)
local part = game.Workspace.Hitbox
local plr = game.Players.LocalPlayer
local char = plr.Character
local hrp = char.HumanoidRootPart
local runservice = game:GetService("RunService")
local uis = game:GetService("UserInputService")
local tweenservice = game:GetService("TweenService")
local cam = workspace.CurrentCamera
local range = 30
local castRayParams = RaycastParams.new()
castRayParams.FilterDescendantsInstances = {part, char:GetDescendants()}
castRayParams.FilterType = Enum.RaycastFilterType.Exclude
local function render()
local mouse2d: Vector2 = uis:GetMouseLocation()
local mouse3dray : Ray = cam:ViewportPointToRay(mouse2d.X, mouse2d.Y, 1)
local raycastresult : RaycastResult = workspace:Raycast(mouse3dray.Origin, mouse3dray.Direction * range, castRayParams)
local mouse3dpos
--print(raycastresult.Distance)
if raycastresult then
mouse3dpos = raycastresult.Position
else
mouse3dpos = (mouse3dray.Origin + mouse3dray.Direction * range)
end
part.CFrame = CFrame.new(mouse3dpos)
end
runservice.Heartbeat:Connect(function()
render()
end)
part.Touched:Connect(function(hit)
print(hit)
end)
You need to be relatively proficient in Networking to pull this off, but here is the step by step:
Update from the client, always, this way your projectile/effect is smooth.
Send a message to the server, telling it to run checks independent of the client, it does not blindly follow the client, but it executes the same code w/o visuals if possible (VFX lag the server and the network unnecessarily here)
If your projectile/effect needs to be visualized to other clients, have the server fire all clients (excluding the original client) and have them run the projectile/effect independently as well.
You can trust the client, and use data from it just for the sake of being smooth and avoiding latency. But since the server runs the same thing independently, you can easily create an anti-cheat to compensate on the server, using sanity-checks and general anti-cheat tactics.
I really recommend you to NOT replicate the hitbox to the server, as it would just increase server lag and network usage.
The reason why you’re not getting the .touched event to things other than your character, is because you’re setting its CFrame, and when you set a part’s CFrame, the touched event doesnt fire with the objects it collides with on the CFrame change, however your character, which runs off of physics, fires the touched event. You can read more on how collisions and touch events behave here
In my opinion, the best thing you could do is call workspace:GetPartBoundsInRadius() onto the sphere to get the parts its “touching”.
You can then send just the results to the server if necessary to handle them.
Wait that’s exactly the solution I was looking for. I can’t thank you enough for this!
I was really just firing remote events using .heartbeat sending data to a script in the hotbox for it to move on the server, which is probably the worst way of doing it.
Thank YOU!