Hey there, I am making an enemy NPC, and it’s working but the only problem is that the script is getting paused because of the MoveToFinished
function, and if I remove it then the NPC won’t follow the paths correctly. Help is appreciated Here’s my code:
local noob = script.Parent
local human = script.Parent:WaitForChild("Humanoid")
local rootpart = script.Parent:WaitForChild("Torso")
local pathfindingservice = game:GetService("PathfindingService")
local paths = game.Workspace:WaitForChild("Paths"):GetChildren()
local dist = 200
local function returnWaypointsAndCreatePath(startPoint, endPoint)
local path = pathfindingservice:CreatePath()
path:ComputeAsync(startPoint, endPoint);
return path:GetWaypoints()
end
local function setNetworkOwner(npc)
for i, v in pairs(npc:GetChildren()) do
if v:IsA("BasePart") then
v:SetNetworkOwner(nil)
end
end
end
local function findTarget()
for index, target in pairs(workspace:GetChildren()) do
if target:IsA("Model") and target:FindFirstChild("Humanoid") and target.Name ~= noob.Name and (target.PrimaryPart.Position - rootpart.Position).Magnitude <= dist then
dist = (target.PrimaryPart.Position - rootpart.Position).Magnitude
return target.PrimaryPart
else
dist = 200;
end
end
return "random", Vector3.new(math.random(-50, 50),0, math.random(-50, 50))
end
local function followPath(startPoint, endPoint)
local waypoints = returnWaypointsAndCreatePath(startPoint, endPoint)
for index, point in pairs(waypoints) do
if point.Action == Enum.PathWaypointAction.Jump then
human.Jump = true
end
human:MoveTo(point.Position);
local reached = human.MoveToFinished:Wait(0.01)
end
end
setNetworkOwner(noob)
while wait() do
local random = Random.new()
local target, vector = findTarget()
if target ~= "random" and vector == nil then
followPath(rootpart.Position, target.Position)
else
followPath(rootpart.Position, rootpart.Position+vector);
end
end
Anyone here gonna help me? if so then pls
Please help anyone. I need to be quick
I’ve run into this issue a few times. Try using magnitude to determine if the NPC reached the position. I find that a magnitude less than or equal to 5 works pretty well.
local RunService = game:GetService([[RunService]])
--Put this where you’re waiting for MoveToFinished():
repeat RunService.Heartbeat:Wait() until (HumanoidRootPart.Position - TargetPosition).magnitude <=5
--Continue your code
But how would I stop the code from being paused?
If you don’t yield at all your NPC will immediately go to the last point in your path.
Yeah I know that, but should I make my own MoveToFinished function and remove the actual MoveToFinished?
For slower yields times yes. Try using magnitude to determine where the NPC is instead of MoveToFinished()
Yeah just did that, should it be like this?
local function moveToFinished(humanoidRoot, targetPosition)
repeat wait() until (humanoidRoot.Position - targetPosition).magnitude <= 5
end
1 Like
Exactly! I do recommend using RunService instead of wait() here because the latter might add unexpected delay to your NPC’s wait time.
Alright, let me add RunService wait here, thank you mate!
1 Like
Here’s another problem, If I am near the NPC, then it won’t go to me, expect it would go to my old position and then come to me.
Can you please share your code now that you’re using magnitude?
Yeah, of course. Here:
local noob = script.Parent
local human = script.Parent:WaitForChild("Humanoid")
local rootpart = script.Parent:WaitForChild("Torso")
local runservice = game:GetService("RunService")
local pathfindingservice = game:GetService("PathfindingService")
local paths = game.Workspace:WaitForChild("Paths"):GetChildren()
local dist = 200
local function moveToFinished(humanoidRoot, targetPosition)
repeat runservice.Heartbeat:Wait() until (humanoidRoot.Position - targetPosition).magnitude <= 10
end
local function returnWaypointsAndCreatePath(startPoint, endPoint)
local path = pathfindingservice:CreatePath()
path:ComputeAsync(startPoint, endPoint);
return path:GetWaypoints()
end
local function setNetworkOwner(npc)
for i, v in pairs(npc:GetChildren()) do
if v:IsA("BasePart") then
v:SetNetworkOwner(nil)
end
end
end
local function findTarget()
for index, target in pairs(workspace:GetChildren()) do
if target:IsA("Model") and target:FindFirstChild("Humanoid") and target.Name ~= noob.Name and (target.PrimaryPart.Position - rootpart.Position).Magnitude <= dist then
dist = (target.PrimaryPart.Position - rootpart.Position).Magnitude
return target.PrimaryPart
else
dist = 200;
end
end
return "random", Vector3.new(math.random(-50, 50),0, math.random(-50, 50))
end
local function followPath(startPoint, endPoint)
local waypoints = returnWaypointsAndCreatePath(startPoint, endPoint)
for index, point in pairs(waypoints) do
if point.Action == Enum.PathWaypointAction.Jump then
human.Jump = true
end
human:MoveTo(point.Position);
moveToFinished(rootpart, waypoints[index].Position)
end
end
setNetworkOwner(noob)
while wait() do
local random = Random.new()
local target, vector = findTarget()
if target ~= "random" and vector == nil then
followPath(rootpart.Position, target.Position)
else
followPath(rootpart.Position, rootpart.Position+vector);
end
end
Edit: Scratch what I wrote for your moveToFinished() function. That was wrong. We need a new function to get the distance because moveToFinished() waits for the distance to be less than 10 to work. My mistake.
So the problem here seems to be that your NPC is following the old path. You will need to recalculate the path the NPC follows often if it’s chasing a player because the target position will always be moving. I recommend breaking the for loop if the player’s distance is too far from the original target position.
Luckily, the closer you are to your target position, the faster pathfinding calculations get. So we can avoid lag if we keep that in mind.
Here’s an example of what I mean:
local function getDistance(humanoidRoot, targetPosition)
return (humanoidRoot.Position - targetPosition).magnitude
end
for index, point in pairs(waypoints) do
if point.Action == Enum.PathWaypointAction.Jump then
human.Jump = true
end
human:MoveTo(point.Position);
local distance = getDistance(rootpart, waypoints[index].Position)
if distance >= 10 then --If the player's distance is greater than 10, break the for loop so we can recalculate a path.
break
end
--Wait for them to reach the position if the player is still close:
moveToFinished(rootpart, waypoints[index].Position)
end
2 Likes
Yeah. Let me try this real quick. If this works, then amazing.
I made a mistake. I edited the code some.
1 Like
Yeah. Seems to work now. Thank you so much!
1 Like