How do I position an object accurately

My problem is this

I’m trying to accurately position an object when the position is moving for example, https://streamable.com/o2kn9u and https://streamable.com/9ls5w2.

This is my code

—LocalScript

local Physics_Run = game:GetService("RunService")
local User_Input = game:GetService("UserInputService")

local User = game.Players.LocalPlayer

local Mouse = User:GetMouse()

local Remotes = script:WaitForChild("Remotes")

local Gun = script.Parent

local Ammo = Gun.Configuration.Ammo
local Max_Ammo = Gun.Configuration.MaxAmmo

local Auto = false
local AutoSpeed = .05

local Click_Began
local Click_Ended

Gun.Equipped:Connect(function()
	Click_Began = User_Input.InputBegan:Connect(function(Input,GPE)
		Auto = true
		
		if Input.UserInputType == Enum.UserInputType.MouseButton1 then
			repeat
				Remotes.Shoot:FireServer(Mouse.Hit.Position)
				
				wait(AutoSpeed)
			until not Auto
		end
	end)
	
	Click_Ended = User_Input.InputEnded:Connect(function(Input,GPE)
		if Input.UserInputType == Enum.UserInputType.MouseButton1 then
			Auto = false
		end
	end)
end)

Gun.Unequipped:Connect(function()
	Click_Began:Disconnect()
	Click_Ended:Disconnect()
end)

—ServerScript

local Gun = script.Parent.Parent

local Ammo = Gun.Configuration.Ammo
local MaxAmmo = Gun.Configuration.MaxAmmo

local Remotes = script.Parent.Remotes

Remotes.Shoot.OnServerEvent:Connect(function(User,Mouse_Location)		
	local RayFilter = RaycastParams.new()
	RayFilter.FilterDescendantsInstances = {User.Character}
	RayFilter.FilterType = Enum.RaycastFilterType.Blacklist
	
	local RayCast = workspace:Raycast(Gun.BulletOffset.Position,(Mouse_Location - Gun.BulletOffset.Position).Unit * 100,RayFilter)
	
	if RayCast then
		local RayPart = Instance.new("Part")
		RayPart.Anchored = true
		RayPart.CanCollide = false
		RayPart.Size = Vector3.new(.3,.3,(Gun.BulletOffset.Position - RayCast.Position).Magnitude)
		RayPart.CFrame = CFrame.lookAt((Gun.BulletOffset.Position + RayCast.Position)/2,RayCast.Position)
		RayPart.Parent = User.Character
		
		game.Debris:AddItem(RayPart,.3)
	end
	
	Ammo.Value = math.clamp(Ammo.Value - 1,0,MaxAmmo.Value)
end)

How would i achieve this?

This is a classic networking problem.

There is nothing wrong with your code, but let me explain to you the issue you are dealing with:
It takes a little bit of time before a message from the client reaches the server (ping). This can be anywhere between 50 ms to 300 ms in Roblox. (On triple-A games this is usually way lower.)

I’m going to use a less than optimal 250 ms ping here to illustrate your problem.

When your client (player) tells the server to make a part, it takes 125 ms to reach the server. When the server creates the part (let’s assume it does that instantly), it would take another 125 ms before you see the part the server just created. 0.250 seconds in total, a noticeable delay that can be seen in your gifs.
It is very important to note that for other clients (other players), the position of the bullet/trail seems ALREADY IN SYNC WITH YOUR CHARACTER. Because your change in movement also takes the same aforementioned 125 ms to reach the server and to replicate.

To fix this, you have a couple of options:

  1. The easiest option, not suitable for competitive FPS games: You make sure the shooter does not see the bullet that the server made. (By deleting it or simply not displaying it.) Instead, you create a local bullet that will be displayed instantly when the shooter fires the gun. You then do hit-detection on the server. (Never do hit-detection on the client*, because cheaters can easily exploit this and tell the server they just headshotted everyone they please.)
    Advantages: Very easy to implement
    Disadvantages: The path of the bullet the client sees versus what other clients (and the server!) see will be different. If you do hit-detection on the server, this might result in ‘headshots’ or hits in general that do not count. (Because you also see other clients 125 ms delayed when compared to the server + the time it takes before your request gets received on the server makes these shots even more inaccurate.)
    In short: A very bad experience for the shooter.

  2. The hardest option: Lag compensation. Make a system that keeps track of your hitboxes for a small period of time. If you see a client with a 250 ms ping, you can simply go back in time to see where the hitboxes of the target player were 125 ms ago. The server can then very accurately check if the shooter hit the target or not. FPS-games like counter strike use a very similar approach.
    For the bullet trail, you could either use the server-calculated one or one similar to option 1, since it’s mostly cosmetics it does not really matter.
    Advantages: You have a reasonably accurate way to check if a hit counted or not.
    Disadvantages: It is a very difficult method to implement, and exploiters could fake their ping in order to gain a little time advantage.
    image

  3. A combination of the aforementioned 2 approaches:
    Use client-sided hit-detection and go back in time on the server to perform sanity checks to see if shots could have been legit. (If they are within a margin of error.)
    Advantages: Very good experience for the shooter.
    Disadvantages: Cheaters could bypass the client-sided detection of hits, making it more likely for them to hit people.

*Only do hit-detection on the client if you can reliably verify the shots on the server. If you don’t, that means cheaters can simply lie to the server and ruin the experience. The server should ALWAYS be involved. For example, the client cannot say to the server ‘hey I headshotted this player and did 100 HP damage.’ This strategy will completely ruin games.

I understand that this can seem very daunting at first, but if you are looking at a serious FPS game, you have to put a lot of work into the shooting systems and networking.

If you are just looking to make a simple roleplaying game (or any other game where gun mechanics are not super important), the first method I suggested might be the best for you.

I hope I was able to help you out.

If you want to do more reading on the subject:
https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

Edit: An easy sanity check to limit the number of requests per remote event: Rate limiter module for Remotes

5 Likes

Thanks, now i understand this way better.

2 Likes