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

NPC Follow system works but after death it stops working [?]

#Goal:# My goal is to create an NPC follow system (I already have the damage system completed). What it should do it if you are within a certain range measured by magnitude you are chased by some NPC's that are within range.

#Problem:# The problem is when a Player first spawns in the NPC chases the player and everything but when the player Dies by something (NPC, another player) the NPC's stop chasing the player. The code works but it stops working sometimes.

#Script:# Note that this is a ServerScript in ServerScriptService

local RunService = game:GetService("RunService")
local Settings = require(game:GetService("ReplicatedStorage").ModuleScripts.SETTINGS)
local Respawn_Time = Settings.BANDIT.RESPAWN_TIME
local plrServ = game:GetService('Players')
local NPCBackup = game:GetService('ServerStorage').NPCBackup.Bandit

local function getClosestPlayer(myPos)
	local pos, tor = Settings.BANDIT.RANGE
	for _, plr in pairs(plrServ:GetPlayers()) do
		if plr.Character then
			if (plr.Character.PrimaryPart.Position - myPos).Magnitude < pos then
				pos = (plr.Character.PrimaryPart.Position - myPos).Magnitude
				tor = plr.Character.PrimaryPart
			end
		end
	end
	return tor
end

local function setupNPC(Bandit, BanditPosition)
	
	local hum = Bandit.Humanoid
	local npcPrimaryPart = Bandit.PrimaryPart
	local targetTorso
	spawn(function() 
		while wait(1) do
			targetTorso = getClosestPlayer(npcPrimaryPart.Position)
			if targetTorso then
				hum:MoveTo(targetTorso.Position, targetTorso)
			else
				return
			end
		end
	end)

	hum.Died:Connect(function()
		wait(Settings.BANDIT.RESPAWN_TIME)
		local cln = NPCBackup:Clone()
		cln:SetPrimaryPartCFrame(BanditPosition)
		cln.Parent = workspace.Bandits
		Bandit:Destroy()
		setupNPC(cln, BanditPosition)
		if not cln:FindFirstChild('RobloxAnimation') then
			local Animation = game:GetService('ServerStorage').Effects.RobloxAnimation:Clone()
			Animation.Disabled = false
			Animation.Parent = cln
			cln.Humanoid.WalkSpeed = Settings.BANDIT.WALKSPEED
		end
	end)
end

for _, Bandit in pairs(workspace.Bandits:GetChildren()) do
	spawn(function() setupNPC(Bandit, Bandit.PrimaryPart.CFrame) end)
end

Hopefully, this problem gets solved, I appreciate any feedback that fixes this issue or improves the code. I try avoiding loops and RunService mostly because I do not know when is the correct time to use a while true do loop and I know that using a loop incorrectly can be studio crashing and game breaking. Thank you for reading.

4 comments

0

Correct me if I'm wrong, but it seems like you only call the setup for each NPC once. That means when the player dies, the NPC can't find the torso and calls "return" in the else function. That would make the NPC stop moving towards the player.

0

I do believe that someone had said this as well on the discord

0

How could I fix this?

0

I would think just removing it would work. If it finds the target it will move. If it doesn't instead of never moving, it will constantly look for a new target.

2 answers

✓ Accepted answer

Although this may no be correct, here is my answer on it

local RunService = game:GetService("RunService")
local Settings = require(game:GetService("ReplicatedStorage").ModuleScripts.SETTINGS)
local Respawn_Time = Settings.BANDIT.RESPAWN_TIME
local plrServ = game:GetService('Players')
local NPCBackup = game:GetService('ServerStorage').NPCBackup.Bandit

local function getClosestPlayer(myPos)
    local pos, tor = Settings.BANDIT.RANGE
    for _, plr in pairs(plrServ:GetPlayers()) do
        if plr.Character then
            if (plr.Character.PrimaryPart.Position - myPos).Magnitude < pos then
                pos = (plr.Character.PrimaryPart.Position - myPos).Magnitude
                tor = plr.Character.PrimaryPart
            end
	else
	   tor = nil --Added this here so if it can't find the player, it will return nil
        end
    end
    return tor
end

local function setupNPC(Bandit, BanditPosition)

    local hum = Bandit.Humanoid
    local npcPrimaryPart = Bandit.PrimaryPart
    local targetTorso
    spawn(function() 
        while wait(1) do
            targetTorso = getClosestPlayer(npcPrimaryPart.Position)
            if targetTorso then
                hum:MoveTo(targetTorso.Position, targetTorso)
		--Removed the else here
            end
        end
    end)

    hum.Died:Connect(function()
        wait(Settings.BANDIT.RESPAWN_TIME)
        local cln = NPCBackup:Clone()
        cln:SetPrimaryPartCFrame(BanditPosition)
        cln.Parent = workspace.Bandits
        Bandit:Destroy()
        setupNPC(cln, BanditPosition)
        if not cln:FindFirstChild('RobloxAnimation') then
            local Animation = game:GetService('ServerStorage').Effects.RobloxAnimation:Clone()
            Animation.Disabled = false
            Animation.Parent = cln
            cln.Humanoid.WalkSpeed = Settings.BANDIT.WALKSPEED
        end
    end)
end

for _, Bandit in pairs(workspace.Bandits:GetChildren()) do
    spawn(function() setupNPC(Bandit, Bandit.PrimaryPart.CFrame) end)
end

You may have to return the torso's position from the getClosestPlayer function, but I don't know for sure. Hopefully this works (which it probably doesn't)! :D

1 comment

0

Thank you

Use this:

local larm = script.Parent:FindFirstChild("Left Arm")
local rarm = script.Parent:FindFirstChild("Right Arm")

function findNearestTorso(pos)
	local list = game.Workspace:children()
	local torso = nil
	local dist = 10
	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("Torso")
			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(0.1)
	local target = findNearestTorso(script.Parent.Torso.Position)
	if target ~= nil then
		script.Parent.Enemy:MoveTo(target.Position, target)
	end
end

3 comments

0

Really... You 1 took a free model, 2. Used a loop when I said I wish to prevent that, 3. Didn't even bother explaining anything (probably because you stole it) but still. Thanks for trying though I gotta give you that

0

Boy, I've been using this in RPG's for years.

0

Lmao search up zombie in workspace and look at the script.

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