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

Pathfinding NPCs Lag in Game, how do i fix?

Asked by 5 years ago

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.

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 129Steve129 7 — 5y
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 mrfrank79 30 — 5y

1 answer

Log in to vote
0
Answered by 5 years ago

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

Ad

Answer this question