My enemy cant catch me

I want to make my enemy chasing me when player in radius
but enemy is not able to catch player no matter how fast it is

I have tried many thing in can find on google but still not able to make it work

local pathfindingService = game:GetService("PathfindingService")
local players = game:GetService("Players")
local runtime = game:GetService("RunService")

local model = script.Parent
local humanoid = model.Humanoid
local observationDistance = 50

local normalSpeed = 10
local chasingSpeed = 60

local function CreatePath(destination)
	local path = pathfindingService:CreatePath({
		AgentRadius = 5,
		AgentHeight = 9,
		AgentCanJump = true
	})
	
	path:ComputeAsync(model.PrimaryPart.Position, destination)
	print(path)
	
	return path
end

local function NearbyPlayer()
	local nearestPlayer
	local minDistance = math.huge
	
	for i, player in pairs(players:GetPlayers()) do
		local character = player.Character or player.CharacterAdded:Wait()
		local distance = (player.Character.PrimaryPart.Position - model.PrimaryPart.Position).Magnitude
		
		if distance > observationDistance then continue end
		
		if distance < minDistance then 
			minDistance = distance
			nearestPlayer = player
		end
	end
	
	
	return nearestPlayer
end

local function MoveTo(destination)
	local player = NearbyPlayer()
	
	if player == nil then
		local path = CreatePath(destination)
		
		humanoid.WalkSpeed = normalSpeed
		
		if path and path.Status == Enum.PathStatus.Success then
			local waypoints = path:GetWaypoints()
			
			for _, waypoint in pairs(waypoints) do
				
				player = NearbyPlayer()
				if player ~= nil then return end
				
				humanoid:MoveTo(waypoint.Position)
				humanoid.MoveToFinished:Wait(2)
			end
			
			humanoid:MoveTo(destination)
		end
	else
		local direction = (model.PrimaryPart.Position - player.Character.PrimaryPart.Position).Unit
		
		humanoid.WalkSpeed = chasingSpeed
		humanoid:Move(direction, false)
	end
end

model.HumanoidRootPart:SetNetworkOwner(nil)

local function ChasingPlayer()
	local player = NearbyPlayer()
	if player == nil then
		
		humanoid.WalkSpeed = normalSpeed
		humanoid:Move(Vector3.new(0, 0, 0), false)
		
		return
	end
	
	local direction = (player.Character.PrimaryPart.Position - model.PrimaryPart.Position).Unit

	humanoid.WalkSpeed = chasingSpeed
	humanoid:Move(direction, false)
end

local function Patrol()
	local waypoints = workspace.Waypoints:GetChildren()
	local randomInt = math.random(1, #waypoints)
	local waypoint = waypoints[randomInt]
	
	MoveTo(waypoint.Position)
end

while runtime.Heartbeat:Wait() do
	--Patrol()
	ChasingPlayer()
end

Remove the number on the Wait() since the script will have to “wait” for the specified number after the humanoid has move to the desired position.

Edit : I didn’t read your code, sorry I guess.

Try changing it to :

while task.wait() do
	--Patrol()
	ChasingPlayer()
end

There is still gap between player and enemy

I think the problem is that the player’s character position changed since the character is moving which will, well, change the position of the character. You can make it so it detect if the player is moving or not, if then “break” the script since the player’s character position has changed.

I have heard someone said that player is run on client and enemy is run on server something like thing when i try to fix it

local playerSpeed = player.Character.PrimaryPart.AssemblyLinearVelocity
	
if playerSpeed ~= Vector3.new(0, 0, 0) then
	return
end

do you mean like this?

No, I mean you need to check if the character’s last position is the same as the new character’s position

I have made a ModuleScript that basically just pathfind the player’s character BUT there was one problem, no matter how far you are the character will always chase you.

I dont use moduleScript but i use script

and my player finder have observation limit so It will stop chasing you at certain distance

Okay, seem kind of simple to implement that.
Edit : just realized that “observationDistance” is just a set max distance lol.

I use ModuleScript for my pathfinding since my game need a lot of pathfinding because it’s a NPC vs Player type of game I think

This has to do with the server-client delay. There are a few things you can do to try and help this.

  1. Make the enemy path find on the client
  2. Make the enemy move in front of the player’s current moving direction & Make the enemy not collide with players, you’ll have to make use of CollisionGroups for this.

everytime the player moves the NPC has to create a new path and therefore it will stop before it can reach the player so what you can do is, when the NPC is within a certain distance from the player it will just move to the player instead of creating a new path to the player.

Test this you must repeat the compute path until he has founded a path

local pathfindingService = game:GetService("PathfindingService")
local players = game:GetService("Players")
local runtime = game:GetService("RunService")

local model = script.Parent
local humanoid = model.Humanoid
local observationDistance = 50

local path = pathfindingService:CreatePath({
	AgentRadius = 5,
	AgentHeight = 9,
	AgentCanJump = true
})

local normalSpeed = 10
local chasingSpeed = 60

local function CreatePath(destination)
	repeat path:ComputeAsync(model.PrimaryPart.Position, destination) until path.Status == Enum.PathStatus.Success
end

local function NearbyPlayer()
	local nearestPlayer
	local minDistance = math.huge

	for i, player in pairs(players:GetPlayers()) do
		local character = player.Character or player.CharacterAdded:Wait()
		local distance = (player.Character.PrimaryPart.Position - model.PrimaryPart.Position).Magnitude

		if distance > observationDistance then continue end

		if distance < minDistance then 
			minDistance = distance
			nearestPlayer = player
		end
	end


	return nearestPlayer
end

local function MoveTo(destination)
	local player = NearbyPlayer()

	if player == nil then
		CreatePath(destination)

		humanoid.WalkSpeed = normalSpeed

		local waypoints = path:GetWaypoints()

		for _, waypoint in pairs(waypoints) do

			player = NearbyPlayer()
			if player ~= nil then return end

			humanoid:MoveTo(waypoint.Position)
			humanoid.MoveToFinished:Wait(1)
		end

		humanoid:MoveTo(destination)
	else
		local direction = (model.PrimaryPart.Position - player.Character.PrimaryPart.Position).Unit

		humanoid.WalkSpeed = chasingSpeed
		humanoid:Move(direction, false)
	end
end

model.HumanoidRootPart:SetNetworkOwner(nil)

local function ChasingPlayer()
	local player = NearbyPlayer()
	if player == nil then

		humanoid.WalkSpeed = normalSpeed
		humanoid:Move(Vector3.new(0, 0, 0), false)

		return
	end

	local direction = (player.Character.PrimaryPart.Position - model.PrimaryPart.Position).Unit

	humanoid.WalkSpeed = chasingSpeed
	humanoid:Move(direction, false)
end

local function Patrol()
	local waypoints = workspace.Waypoints:GetChildren()
	local randomInt = math.random(1, #waypoints)
	local waypoint = waypoints[randomInt]

	MoveTo(waypoint.Position)
end

while runtime.Heartbeat:Wait() do
	--Patrol()
	ChasingPlayer()
end

These are functionally identical.


To OP: Set the network owner to the server and remove the move finished wait and make your own system for that. Then, use Humanoid:Move instead of MoveTo so it doesn’t stop.