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

(Depressed) Ninja Pathfinding AI is quite buggy (?)

Hello Developers!

I created a NPC which is called: "Sad Ninja". Anyway, the NPC has a Pathfinding script which will activate once someone damages the NPC. The Issue however is that the NPC Pathfinding script is buggy, let me explain. When the NPC is chasing a player, the NPC will usually briefly stop in place which makes the NPC looks like it's lagging

Script:

--//NPC\\--
local NPC = script.Parent
local Humanoid = NPC.Humanoid
local OldHealth = Humanoid.Health
--//Services\\--
local RunService = game:GetService("RunService")
local Pathfinding = game:GetService("PathfindingService")
local Players = game:GetService("Players")
--//Functions\\--
local function Jump()
	Humanoid.Jump = true
end
local function FindNearestPlayer()
	local RadiusToFindUser = 500
	local Target = nil
	for i,v in pairs(Players:GetChildren()) do
		if v:IsA("Player") then
			local PrimaryPart = v.Character.PrimaryPart
			if (PrimaryPart.Position-NPC.HumanoidRootPart.Position).Magnitude < RadiusToFindUser then
				local Path = Pathfinding:CreatePath()
				Path:ComputeAsync(PrimaryPart.Position, NPC.HumanoidRootPart.Position)
				if Path.Status == Enum.PathStatus.Success then
					local Positions = Path:GetWaypoints()
					for i,v in pairs(Positions) do
						local Position = Instance.new("Part",game.Workspace)
						game:GetService("Debris"):AddItem(Position,1)
						Position.Anchored = true
						Position.Transparency = 1
						Position.CanCollide = false
						Position.Position = v.Position
						Humanoid:MoveTo(PrimaryPart.Position)
					end
				end
			end
		end
	end
end
local function Disappear()
	for _, BodyPart in ipairs(NPC:GetChildren()) do
		if BodyPart:IsA("BasePart") then
			BodyPart.Transparency = 1
		end
	end
	NPC.Torso.CFrame = NPC.Torso.CFrame * CFrame.new(math.random(-5,5),0,math.random(-5,5))
	wait(3)
	for _, BodyPart in ipairs(NPC:GetChildren()) do
		if BodyPart:IsA("BasePart") then
			BodyPart.Transparency = 0
		end
	end
	NPC.HumanoidRootPart.Transparency = 1
	RunService.Heartbeat:Connect(function()
		FindNearestPlayer()
	end)
end
--//FireFunctions\\--
Humanoid.HealthChanged:Connect(function(newHealth)
	local healthDifference = OldHealth - newHealth
	if newHealth < OldHealth then
		Disappear()
	end
	OldHealth = newHealth
end)

1 answer

✓ Accepted answer

It's more likely because of Network Ownership. By default, all parts except the players' limbs are owned by the Server. Anchored parts are always owned by the Server, while unanchored parts are not. If a player's character gets near an unanchored part, the game engine will automatically set its network ownership to the player's client. That might cause a problem to the part.

If a part's network owner is not the Server and is one of the clients, it can cause lag to the part if the network owner is lagging. To the network owner, the client, it seems that it is just doing fine, it is not lagging; but to the other clients with better connection and the Server, it is lagging.

And that could be why you're Ninja NPC is buggy. The network owner of the NPC's limbs is the target player being chased. To fix that, we will set every limb of the NPC, every accessory (if they have one), and tool handles (if they have one) network ownership to the Server using BasePart:SetNetworkOwner(nil).

Just simply attach this to the end of your code and it should solve it.

while true do -- we will loop this to detect if network ownership changes
	for _, descendant in ipairs(NPC:GetDescendants()) do -- we will iterate every descendant of the NPC
		if descendant:IsA("BasePart") then -- if descendant is a part
			if descendant:GetNetworkOwner() ~= nil then -- if network owner is not the Server
				descendant:SetNetworkOwner(nil) -- sets network ownership to the Server
			end
		end
	end
	
	task.wait() -- in case if the for loop above didn't yield/was super fast, we will add a yielding (waiting/delaying) function in the while loop to avoid script timeout (script timeouts can lag your game or worse, break your game; script timeouts happen when loops don't yield and is going super duper fast, almost 0 seconds of yield before repeating)
end

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