Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Pathfinding NPCs Lag in Game, how do i fix?

I've seen many players reporting this problem but i can never seem to update my script to fix this problem. When NPCs are wandering, they always seem to stop and start moving, along with a short pause of animation. some people say things about humanoid.MoveToFinished:Wait() but i'm not sure if it has anything to do with the script i'm using. Here is the script I am using, be warned it's long.

	local players = Info.Players:GetPlayers()
	local closestCharacter, closestCharacterDistance

	for i=1, #players do
		local player = players[i]
		
		if player.Neutral or player.TeamColor ~= Settings.FriendlyTeam.Value then
			local character = player.Character
	
			if character ~= nil and character:FindFirstChild('Humanoid') ~= nil and character.Humanoid:IsA('Humanoid') then
				local distance = player:DistanceFromCharacter(Monster:GetCFrame().p)
	
				if distance < Monster:GetMaximumDetectionDistance() then
					if closestCharacter == nil then
						closestCharacter, closestCharacterDistance = character, distance
					else
						if closestCharacterDistance > distance then
							closestCharacter, closestCharacterDistance = character, distance
						end
					end
				end
			end
		end
	end


	if closestCharacter ~= nil then
		Mind.CurrentTargetHumanoid.Value = closestCharacter.Humanoid
	end
end

function Monster:TryRecomputePath()
	if Data.AutoRecompute or tick() - Data.LastRecomputePath > 1/Info.RecomputePathFrequency then
		Monster:RecomputePath()
	end
end

function Monster:GetTargetCFrame()
	local targetHumanoid = Mind.CurrentTargetHumanoid.Value
	
	if Monster:TargetIsValid() then
		return targetHumanoid.Torso.CFrame
	else
		return CFrame.new()
	end
end

function Monster:IsAlive()
	return Self.Humanoid.Health > 0 and Self.Humanoid.Torso ~= nil
end

function Monster:TargetIsValid()
	local targetHumanoid = Mind.CurrentTargetHumanoid.Value
	
	if targetHumanoid ~= nil and targetHumanoid:IsA 'Humanoid' and targetHumanoid.Torso ~= nil and targetHumanoid.Torso:IsA 'BasePart' then
		return true
	else
		return false
	end
end

function Monster:HasClearLineOfSight()
	-- Going to cast a ray to see if I can just see my target
	local myPos, targetPos = Monster:GetCFrame().p, Monster:GetTargetCFrame().p
	
	local hit, pos = Workspace:FindPartOnRayWithIgnoreList(
		Ray.new(
			myPos,
			targetPos - myPos
		),
		{
			Self,
			Mind.CurrentTargetHumanoid.Value.Parent
		}
	)
	
	
	if hit == nil then
		return true
	else
		return false
	end
end

function Monster:RecomputePath()
	if not Data.Recomputing then
		if Monster:IsAlive() and Monster:TargetIsValid() then
			if Monster:HasClearLineOfSight() then
				Data.AutoRecompute = true
				Data.PathCoords = {
					Monster:GetCFrame().p,
					Monster:GetTargetCFrame().p
				}
				
				Data.LastRecomputePath = tick()
				Data.CurrentNode = nil
				Data.CurrentNodeIndex = 2 -- Starts chasing the target without evaluating its current position
			else
				-- Do pathfinding since you can't walk straight
				Data.Recomputing = true -- Basically a debounce.
				Data.AutoRecompute = false
				
				
				local path = Info.PathfindingService:ComputeSmoothPathAsync(
					Monster:GetCFrame().p,
					Monster:GetTargetCFrame().p,
					500
				)
				Data.PathCoords = path:GetPointCoordinates()
				
				
				Data.Recomputing = false
				Data.LastRecomputePath = tick()
				Data.CurrentNode = nil
				Data.CurrentNodeIndex = 1
			end
		end
	end
end

function Monster:Update()
	Monster:ReevaluateTarget()
	Monster:SearchForTarget()
	Monster:TryRecomputePath()
	Monster:TravelPath()
end

function Monster:TravelPath()
	local closest, closestDistance, closestIndex
	local myPosition = Monster:GetCFrame().p
	local skipCurrentNode = Data.CurrentNode ~= nil and (Data.CurrentNode - myPosition).magnitude < 3
	
	for i=Data.CurrentNodeIndex, #Data.PathCoords do
		local coord = Data.PathCoords[i]
		if not (skipCurrentNode and coord == Data.CurrentNode) then
			local distance = (coord - myPosition).magnitude
			
			if closest == nil then
				closest, closestDistance, closestIndex = coord, distance, i
			else
				if distance < closestDistance then
					closest, closestDistance, closestIndex = coord, distance, i
				else
					break
				end
			end
		end
	end
	
	
	--
	if closest ~= nil then
		Data.CurrentNode = closest
		Data.CurrentNodeIndex = closestIndex
		
		local humanoid = Self:FindFirstChild 'Humanoid'
		
		if humanoid ~= nil and humanoid:IsA'Humanoid' then
			humanoid:MoveTo(closest)
		end
		
		if Monster:IsAlive() and Monster:TargetIsValid() then
			Monster:TryJumpCheck()
			Monster:TryAttack()
		end
		
		if closestIndex == #Data.PathCoords then
			-- Reached the end of the path, force a new check
			Data.AutoRecompute = true
		end
	end
end

Hope there is something that can be done about this. Also, sorry for the long script again.

2 comments

0

Same i figured out it takes some time for it to recalculate a path to a player for my npc it stops more the closer it gets to the player ...stops as in kinda bumpy stopping

0

Exactly, but my NPCs stop when trying to walk around solid parts, if the player were to be in a straight line from the NPC without any obstacles, then it will not lag

1 answer

✓ Accepted answer

Just type this

local h = script.Parent.Humanoid 
local torso = script.Parent.UpperTorso --Torso if Mob is r6 UpperTorso if Mob is r15 
local spawnCF = torso.CFrame 
function findPlayer() 
 for _,v in next, game.Players:GetPlayers() do 
if v.Character then 
local char = v.Character if char:FindFirstChild("Humanoid") and char:FindFirstChild("UpperTorso") then --Torso if Player is r6 UpperTorso if Player is r15 
local ptorso = char.UpperTorso --Torso if Player is r6 UpperTorso if Player is r15 
if (ptorso.Position - torso.Position).magnitude <= 20 then 
 return v 
end 
end
 end 
end 
return nil 
end 
while wait() do 

local player = findPlayer()
 if player ~= nil then 
h.WalkToPoint = player.Character.UpperTorso.Position --Torso if Player is r6 UpperTorso if Player is r15 
else h.WalkToPoint = spawnCF.p
end 
 end

This discussion is preserved as it was. New answers, comments, and votes are closed.