Chase NPC lags behind on client

I’m trying to make an enemy npc with various close ranged attacks when they get right up to the player. But if the player is moving away, the npc is always like 1-2 persons behind on the client, whereas on the server its like less than a stud behind but still better than nothing. I set the network owner to nil. The NPC also has 2x the walkspeed.

I know there’s delays between server and client but the npc is really far away to the point the attacks don’t line up.

you can try set npc networkowner when its close to closest player then nil when its far

On nil it just makes it quicker on the server, I want it to not be delayed for the client. If I set it to the player it’s delayed on both ends

it shouldn’t be since it is on player ownership. did you check the ownership?

yes, this is my script:

local npc = script.Parent
local humanoid = npc:WaitForChild("Humanoid")
local rootPart = npc:WaitForChild("HumanoidRootPart")

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

local targetPlayer = nil

local function findNearestPlayer()
	local nearestDistance = math.huge
	local nearestPlayer = nil
	for _, player in pairs(Players:GetPlayers()) do
		if player.Character and player.Character:FindFirstChild("HumanoidRootPart") then
			local distance = (player.Character.HumanoidRootPart.Position - rootPart.Position).Magnitude
			if distance < nearestDistance then
				nearestDistance = distance
				nearestPlayer = player
			end
		end
	end
	return nearestPlayer
end

local function chasePlayer()
	while true do
		if targetPlayer and targetPlayer.Character and targetPlayer.Character:FindFirstChild("HumanoidRootPart") then
			local targetPosition = targetPlayer.Character.HumanoidRootPart.Position
			humanoid:MoveTo(targetPosition)
		end
		wait()
	end
end

local function setNetworkOwner(npc, player)
	if npc:IsA("Model") and npc.PrimaryPart then
		npc.PrimaryPart:SetNetworkOwner(player) --set ownership
	end
end

RunService.Heartbeat:Connect(function()
	local nearestPlayer = findNearestPlayer()
	if nearestPlayer ~= targetPlayer then
		targetPlayer = nearestPlayer
		if targetPlayer then
			setNetworkOwner(npc, targetPlayer)
		end
	end
end)

spawn(chasePlayer)

To manually force a delay so that the client can see as if it is on target may require a “HitBox” part to be welded onto the npc dummy somewhere towards its backside

use that HitBox part to determine the proper time to strike so the client can see that he is definitely in range. (perhaps distance magnitude checks, not sure how you determine when to attack since that code is not provided)

the problem is the NPC never reaches the player when walking, only when they stop, I want them to catch up to the player since that’s the point of them being faster

The root of the issue is network delay, which you can’t really do much about. However, if you were to simulate the finer movements of the NPC on each client individually, or at least the current one the NPC is targeting.

Essentially, you’d have two NPCs, one on the client and one on the server. Obviously the client won’t be able to see the server-sided one, only the one they are simulating. The server will use remote events to tell the clients what the NPC is targeting so the clients can use that information to move their clone of the NPC. Ideally, the single-target attacks should also have their hitboxes calculated on the targeted client for the best smoothness.

Last thing to worry about is security. The server will still act as the final judge of hitboxes and still command the general actions of the NPC. If the info sent by the client is ever too wonky, you can use the server-sided NPC for calculations.