Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

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

Asked by 1 year ago

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

Log in to vote
1
Answered by 1 year ago
Edited 1 year ago

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
Ad

Answer this question