What do you want to achieve?
I’m making a gun chassis using the FastCast Module, and need to fire the bullet to the center of the screen; hence using ViewportPointToRay()
What is the issue?
I have two bullets fired; client replication from a View Model, and server replication from the Character’s Tool, if I fire into a part that is within the range of the gun, the two bullets will hit at different locations. For example:
What solutions have you tried so far?
I’m not too familiar with rays, and have looked on the robloxdev website, I could use Mouse.Hit, but it’s not reliable if I were to make a FPS compatible with PC + Mobile. I am looking for an alternative or something that can be added on to my current script.
Here’s a snippet of my current script, I need to retain the center value and fireDirection in order for FastCast to do its thing:
local vp = camera.ViewportSize
local screenCenter = camera:ViewportPointToRay(vp.X/2, vp.Y/2)
local centerRay = Ray.new(screenCenter.Origin, screenCenter.Direction*config.Range.Value)
center = centerRay.Origin + centerRay.Direction.Magnitude * centerRay.Direction.Unit
fireDirection = (center - firePoint.WorldPosition).Unit
Latency will always make it where your server bullet will be behind your client bullet.
Just let the client do the hit detection, and the server just some basic sanity checks.
This is what most top page games do (Like Arsenal and Phantom Forces).
If your just talking about the FastCast bullet, let the client pass the hit position of the Ray as well, and the server just follow that.
I am letting the client pass the hit position, I’m just not sure how to get the ray from the center of the screen to detect a hit part. If you look in the diagram, latency is not the problem, the bullets stop in completely different places because they’re travelling to the end of the ray from different positions (since the View Model barrel position is not always at the Character’s tool.
I just finished making a gun, and what I did was allow the client to pass the start position, and I verify it by checking the distance relative to anyone of the character’s arm.
The view model’s gun will always be centered, and since it’s a FPS game, the character’s tool will also rotate relative to the camera’s position (only on the Y-Axis, since I’d rather not implement server sided body rotation; looking up and down).
Yeah but it’s not as simple as you think because remember when you look upwards and downwards in FPS view your character will still be still be upright so its not like the offset would be constant, the best thing to do as I said earlier would be the let the client pass the start position and you verify it, since you wont be replicating the tilting to the server.
I could definitely be wrong, but to my understanding: both bullets start at their fire points and end at the end of the ray I casted from the center of the screen (length of the ray is the range of gun). They won’t hit at the same spot if they can’t reach the end of the ray. Which is why I need to detect a hitpart and adjust the end of the ray accordingly.
if you want to trust the client’s hit detection, you can try this
e.OnServerEvent:Connect(function(player, charToolFirePart, bulletPosition)
local ray = Ray.new(charToolFirePart.Position, (bulletPosition - charToolFirePart.Position).Unit * ((charToolFirePart.Position - bulletPosition).Magnitude + 0.1))
local part, pos, normal = workspace:FindPartOnRay(ray)
end)
although i dont really see the purpose of making a second ray, since if you are already trusting the client’s position you can just put the bullet hole in the position
like this
e.OnServerEvent:Connect(function(player, bulletPosition)
local pos = bulletPosition -- you dont even need this variable here, just the argument from the onServerEvent
end)
After tinkering around for a bit and a lesson about Raycasting, I found a solution:
local vp = camera.ViewportSize
local screenCenter = camera:ViewportPointToRay(vp.X/2, vp.Y/2)
local hitPart, endPos = workspace:FindPartOnRayWithIgnoreList(Ray.new(screenCenter.Origin,
screenCenter.Direction*config.Range.Value), {char, workspace:WaitForChild("BulletsFolder")})
fireDirection = (endPos - firePoint.WorldPosition).Unit
clientFireDirection = (endPos - viewModelFirePoint.WorldPosition).Unit
Turns out I could’ve just reused the viewport ray in :FindPartOnRay() to find the proper end position of the ray and calculate the firing direction from there. However, I really appreciate everyone’s replies to try and help me!