Linear Velocity Projectile Inconsistencies

I’m trying to make a projectile that moves toward the mouse position using LinearVelocity, but I’m running into a few problems. If anyone has advice, I’d appreciate the help:

Inconsistent speed – When aiming close to the target, the projectile moves slowly. But when aiming farther (especially when aiming in the sky), it moves way faster.
Client-server desync – As shown in the image, the red projectile on the server doesn’t match up with what the client sees (this is acting as the hitbox). On the client, the projectile appears to move faster than what the server is replicating.

Should I be setting network ownership to the player to fix this? Or is there a better way to keep everything in sync while still keeping performance good

Server

local RS = game:GetService("RunService")

game.ReplicatedStorage.RemoteEvent.OnServerEvent:Connect(function(plr, hit)
	local Connection: RBXScriptConnection
	local cframe = plr.Character.PrimaryPart.CFrame * CFrame.new(0,0,-1)
	local ice = game.ReplicatedStorage["ice slash1"]:Clone()

	ice.CFrame = cframe * CFrame.new(0, 4, -2)
	ice.BrickColor = BrickColor.new("Really red")
	ice.Transparency = 0.5
	ice.Name = workspace:GetServerTimeNow().."Server"

	ice.Parent = workspace

	local pos = (hit- ice.Position)

	ice.LinearVelocity.VectorVelocity = pos
		

	game.ReplicatedStorage.RemoteEvent:FireAllClients(cframe, pos)

	
	local CastParams = RaycastParams.new()
	CastParams.FilterDescendantsInstances = {ice, plr.Character}
	CastParams.FilterType = Enum.RaycastFilterType.Exclude
	local Distance = 5
	local start = tick()
	Connection = RS.Stepped:Connect(function()
		if tick() - start > 20 then
			Connection:Disconnect()
			return
		end
		
		for angle = 0, 360 - 60, 60 do
			local radians = math.rad(angle)
			local direction = Vector3.new(math.cos(radians), 0, math.sin(radians)) * Distance
			local result = workspace:Raycast(ice.Position, direction, CastParams)

			if result then
				Connection:Disconnect()
				
				print(`hit {result.Instance.Name}`)
				
				return
			end
		end
	end)
end)

Client

game.ReplicatedStorage.RemoteEvent.OnClientEvent:Connect(function(cframe, pos)
	local ice = game.ReplicatedStorage["ice slash1"]:Clone()
	ice.CFrame = cframe
	ice.Name = workspace:GetServerTimeNow().."Client"
	ice.Parent = workspace

	ice.LinearVelocity.VectorVelocity = pos
end)


?

1 Like

I’ve also experienced inconsistencies with syncing stuff like this, never for a reliable solution. Commenting to bump + follow thread, would love to know solution as well :slight_smile:

You need to turn it into a consistent unit. See Vector3.Unit

you’ve got your entire system incorrect. client/server desync is the main issue you are having here, and the way you have structured it makes the hitbox always desync with the visual. to fix this, you should instead fire either the instance name (if it is unique and findable in a folder) or the instance itself so the client can clone it or reference the starting position of it. if the fired instance is nil, we can assume streaming either has not loaded it or the server destroyed the part before the client received the remote event. as for position desync, check what nowodev said about making the pos variable a unit vector