NPC Movement issues, with starting position not existing

Hello everyone reading this post, thanks for taking the time out of your day to try and help me out with this… I’m not new to Roblox development, but I recently came back after a long break, and I’ve been trying to get back on track with my projects, and I’ve been experiencing some issues with my NPC Movement system.

The code included is the entire system for the npcs, the issue occurs when the npc dies for the 1st time, since the system fails to find the “StartPosition”, which marks the npc’s start position, so when the player is out of reach the npc returns to the original position.

Here’s the error I’ve been getting:

devforumhelp

I tried out a lot of different things, including adding waits for the start position, resulting in infinite yields, which break the entire thing… The final conclusion is that everything I try to do breaks the thing completely… as soon as the NPC dies, it breaks… although other NPC’s still work, before getting killed for the 1st time.

-- VARIABLES --

local moveInterval = 0.3
local posOffset = Vector3.new(-1, 1, -1)

local noobs = workspace.Noobs:GetDescendants()

local attackRunning
local attackId = "http://www.roblox.com/Asset?ID=5147386264"

-- FINDING THE CLOSEST PLAYER --

local function findPlayer(enemy)
	local closestPlayer
	local closest
	
	for i, v in pairs(game.Players:GetChildren()) do
		if v.Character then
			if v.Character.Humanoid then
				if v.Character.HumanoidRootPart then
					if not enemy:FindFirstChild("HumanoidRootPart") then return nil end
					
					local distance = v:DistanceFromCharacter(enemy.HumanoidRootPart.Position)
					
					if (not closestPlayer or closest < distance) and distance < 20 then
						closestPlayer = v
						closest = distance
					end
					
				end
			end
		end
		
	end
	return closestPlayer
end

-- MOVEMENT --

local function move(player, enemy)
	local desiredPosition
	
	if not player then
		desiredPosition = enemy.StartPosition.Value
	else
		desiredPosition = player.Character.HumanoidRootPart.Position
	end
	
	if enemy.Humanoid.Health > 0 then
		enemy.Humanoid:MoveTo(desiredPosition + posOffset, player)
	end
	
end

-- ATTACK FUNCTION --

local animateEvent = game:GetService("ReplicatedStorage").Assets.Remotes.Main:WaitForChild("Animate")

local function attack(player, enemy)
	for _, item in pairs(enemy:GetChildren()) do
		
		if item:IsA("MeshPart") or item:IsA("Part") then
			
			local touchConnection
			
			touchConnection = item.Touched:Connect(function(object)
				
				if attackRunning ~= true and player and enemy.Humanoid.Health > 0 then
					attackRunning = true
					
					while player:DistanceFromCharacter(enemy.HumanoidRootPart.Position) < 7 do
						animateEvent:FireAllClients(attackId, enemy.Humanoid)
						
						wait(2)
						
						if enemy.Humanoid.Health > 0 and player:DistanceFromCharacter(enemy.HumanoidRootPart.Position) < 5 then
							player.Character.Humanoid:TakeDamage(5)
						end
					end
					attackRunning = false
				end	
				touchConnection:Disconnect()
			end)
		end
	end
end

-- CONNECTING FUNCTIONS --

local function update(enemy)
	
	local player = findPlayer(enemy)
	print(player)
		
	move(player, enemy)
	attack(player, enemy)
	
end

-- START POSITION, DEATH HANDLER --

for i, noob in ipairs(noobs) do
	if noob:IsA("Model") then
		
		local startPosition = noob.HumanoidRootPart.Position
		local vectorValue = Instance.new("Vector3Value") vectorValue.Name = "StartPosition"
		
		vectorValue.Value = startPosition		
		vectorValue.Parent = noob
		
		local clone = noob:Clone()
		
		noob.Humanoid.Died:Connect(function()
			wait(8)
			clone.Parent = workspace.Noobs
			noob:Destroy()
		end)
		
	end
end

-- UPDATING EVERYTHING --

while wait(moveInterval) do
	for i, v in ipairs(noobs) do
		if v:IsA("Model") then
			update(v)
		end
	end
end

Thanks for taking the time, and trying to help me with this situation.

1 Like

Jeez, its 1 a.m. Can you explain what this line does? You are creating a value and parenting it to the noob, but then they die later on meaning that the value is nil?

This line is creating a vector value of the starting position of the noob, which then get’s clone via the noob:Clone().

Can you add in some prints near the end of your code. Also what is the enemy in this case? Is there a startposition Value in your enemy? Gonna get some rest tho

Adding waits resulting in infinite yields. That mean’s your script is not waiting for you “start positions”. Or possibly it cannot find “start positions” when your noobs die. Do the noobs respawn? if not you won’t be able to call their required functions.