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

My Pathfinding Zombies Still Aren't Very Smart, Any Help?

Asked by 7 years ago

A while ago, I changed the zombies' AI in my game, Zombie Attack, from the drooling zombie's AI to a more basic one, the old findnearesttorso AI used in many zombie models. Most of the maps I've made for the game are an open area with no walls, (excluding the borders of the map) but I've started work on a map with multiple buildings to explore. Since the zombies only move to your position, they can get stuck on walls, and ultimately, the game would take longer to finish because players would spend all their time finding where all the zombies were piled up at. So recently, I've decided to give pathfinding a try, and it works! Well, mostly. The zombies do find a path to you, and they follow that path, but they will stick to that path for the rest of the time it takes them to get there. That presents 2 problems. Even if the player moves, the zombie will continue following the current path, and won't create a new one if the player strays too far from the end of the path, which can make it seem like the zombie is chasing nothing. The other problem is if something moves in front of the zombie, whether it's a wall (extremely unlikely) or another zombie. (eh, it could happen) The zombie will get stuck on this and never make it to the next point of their path, pretty much making the zombie cannon fodder for whoever gets to it first. The wiki says to use CheckOcclusionAsync, but it's not very descriptive on how it works, and I'm pretty much lost on that part.

Anyways, here's my code. Please tell me what I can do to fix this, or at least help me out on it. Thanks! (I got the pathfinding parts from the wiki, since I was pretty much clueless on how to use pathfinding prior to this.) My best guess for a solution to problem #1 is to detect whether or not the player's position is the same as the final point on the path's position, then use return to restart the loop and find a new path if it isn't, but I'm not sure on how to get the position of the final point. (I'm not very experienced when it comes to tables)

wait()
local statsscript = require(script.Parent.Stats)
local enemies = script.Parent.EnemyFolder.Value

function findNearestTorso(pos)
    local list = enemies:GetChildren()
    local torso = nil
    local dist = 500
    local temp = nil
    local human = nil
    local temp2 = nil
    for x = 1, #list do
        temp2 = list[x]
        if (temp2.className == "Model") and (temp2 ~= script.Parent) then
            temp = temp2:findFirstChild("HumanoidRootPart")
            human = temp2:findFirstChild("Humanoid")
            if (temp ~= nil) and (human ~= nil) and (human.Health > 0) then
                if (temp.Position - pos).magnitude < dist then
                    torso = temp
                    dist = (temp.Position - pos).magnitude
                end
            end
        end
    end
    return torso
end

while true do
    wait()
    local target = findNearestTorso(script.Parent.HumanoidRootPart.Position)
    if target then
        local path = game:GetService("PathfindingService"):ComputeSmoothPathAsync(script.Parent.HumanoidRootPart.Position, target.Position, 500)
        local points = path:GetPointCoordinates()
        for _, point in ipairs(points) do
            script.Parent.Humanoid:MoveTo(point)
            repeat
                distance = (point - script.Parent.HumanoidRootPart.Position).magnitude
                wait()
            until distance < 3
        end
    end
end

1 answer

Log in to vote
0
Answered by 7 years ago

You should NOT be looping through the table got from :GetPointCoordinates(). Instead, do this:

while wait() do
    local target = findNearestTorso(script.Parent.HumanoidRootPart.Position)
    if target then
        local path = game:GetService("PathfindingService"):ComputeSmoothPathAsync(script.Parent.HumanoidRootPart.Position, target.Position, 500)
        local points = path:GetPointCoordinates()
       if #points > 1 then
             script.Parent.Humanoid:MoveTo(points[2])
       end
    end
end

this way, your zombie can get to the player, even if the player moves. The reason that we dont move to the first vector3 value in the table is that it is where the NPC is (correct me if im wrong). Sometimes the second value also doesn't work so you can try the third one, as shown in this example code (not the best):

if #points > 2 then
humanoid:MoveTo(points[3])
elseif #points > 1 then
humanoid:MoveTo(points[2])
end
0
It works perfectly! Thank you so much! :D WesleyTheSkunk 12 — 7y
0
Well, almost perfectly. The zombie chases me as it's supposed to, but there's one big problem. Lag. Whenever I'm above the zombie and it's trying to chase me, the game gets really laggy. My guess is the zombie is repeatedly making paths to follow to get to me while I'm in the air and that lags out the game, but I'm not sure. Any help on that one? WesleyTheSkunk 12 — 7y
0
slow the loop down to running 1/5 of a second instead every 1/30th of a second (what i have for my npcs). User#14829 0 — 7y
Ad

Answer this question