Attempt to get length of a nil value

If it is in the non-passable area, it is judged that there is no enemytorso, and if it is in the non-passable area, an error occurs.

If you solved this kind of error, please explain to me the reason why you solved it

local SearchDistance = 100000 

local aiDamage = 0 

local canWander = false
local WanderX, WanderZ = 30, 30

local function getHumanoid(model)
	for _, v in pairs(model:GetChildren()) do
		if v:IsA("Humanoid") then
			return v
		end
	end
end

local ai = script.Parent
local human = getHumanoid(ai)
local hroot = ai.HumanoidRootPart
local zspeed = hroot.Velocity.magnitude

local PathfindingService = game:GetService("PathfindingService")
local Workspaces = game:GetService("Workspace")
local Players = game:GetService("Players")

local function GetPlayerNames()
	local players = Players:GetChildren()
	local name = nil
	for _, v in pairs(players) do
		if v:IsA("Player") then
			name = tostring(v.Name)
		end
	end
	return name
end

local function GetPlayersBodyParts(t)
	local torso = t
	if torso then
		local figure = torso.Parent
		for _, v in pairs(figure:GetChildren()) do
			if v:IsA("Part") then
				return v.Name
			end
		end
	else
		return "HumanoidRootPart"
	end
end

local function GetTorso(part)
	local chars = Workspaces:GetChildren()
	local torso = nil
	for _, v in pairs(chars) do
		if v:IsA("Model") and v ~= script.Parent and v.Name == GetPlayerNames() then
			local charRoot = v:FindFirstChild("HumanoidRootPart")
			if (charRoot.Position - part).magnitude < SearchDistance then
				torso = charRoot
			end
		end
	end
	return torso
end

for _, zambieparts in pairs(ai:GetChildren()) do
	if zambieparts:IsA("Part") then
		zambieparts.Touched:connect(function(p)
			if p.Parent.Name == GetPlayerNames() and p.Parent.Name ~= ai.Name then 
				local enemy = p.Parent
				local enemyhuman = getHumanoid(enemy)
				enemyhuman:TakeDamage(aiDamage)
			end
		end)
	end
end

local path
local waypoint
local oldpoints
local isWandering = 0

if canWander then
	spawn(function()
		while isWandering == 0 do
			isWandering = 1
			local desgx, desgz = hroot.Position.x + math.random(-WanderX, WanderX), hroot.Position.z + math.random(-WanderZ, WanderZ)
			human:MoveTo( Vector3.new(desgx, 0, desgz) )
			wait(math.random(4, 6))
			isWandering = 0
		end
	end)
end

local function checkw(t)
	local ci = 3
	if ci > #t then
		ci = 3
	end
	if t[ci] == nil and ci < #t then
		repeat
			ci = ci + 1
			wait()
		until t[ci]
		return Vector3.new(1, 0, 0) + t[ci]
	else
		ci = 3
		return t[ci]
	end
end

while wait() do
	local enemytorso = GetTorso(hroot.Position)	
	if enemytorso then 
		isWandering = 1

		local path = PathfindingService:CreatePath{
			Costs = {}
		}

		path:ComputeAsync(hroot.Position, enemytorso.Position)

		if path.Status == Enum.PathStatus.Success then
			waypoint = path:GetWaypoints()
			oldpoints = waypoint
			local connection = nil

			local direct = Vector3.FromNormalId(Enum.NormalId.Front)
			local ncf = hroot.CFrame * CFrame.new(direct)
			direct = ncf.p.unit
			local rootr = Ray.new(hroot.Position, direct)
			local phit, ppos = Workspaces:FindPartOnRay(rootr, hroot)

			if path and waypoint or checkw(waypoint) then
				if checkw(waypoint) and checkw(waypoint).Action == Enum.PathWaypointAction.Walk then
					human:MoveTo(checkw(waypoint).Position)
					human.Jump = false
				end
				if checkw(waypoint) and checkw(waypoint).Action == Enum.PathWaypointAction.Jump then
					human:MoveTo(checkw(waypoint).Position)
					human.Jump = true
				end
			end

			if connection then
				connection:Disconnect()
			end
		else
			for i = 3, #oldpoints do
				human:MoveTo( oldpoints[i].Position )	
			end
		end
	elseif enemytorso == nil and canWander then
		isWandering = 0
		path = nil
		waypoint = nil
		human.MoveToFinished:Wait()
	end
end

I thought there was an error

			for i = 3, #oldpoints do
				human:MoveTo( oldpoints[i].Position )	
			end

The explanation is over

where is oldpoints defined, I don’t see it anywhere in your script

local oldpoints
waypoint = path:GetWaypoints()
oldpoints = waypoint

Is this what you’re trying to say?

This is your code as I see it, with some of the irrelevant fluff removed.

	if enemytorso then 
		if path.Status == Enum.PathStatus.Success then
			waypoint = path:GetWaypoints()
			oldpoints = waypoint
		else
			for i = 3, #oldpoints do
				human:MoveTo( oldpoints[i].Position )	
			end
		end

What happens if path.Status ~= Enum.PathStatus.Success on the first iteration, before oldpoints has been set?

1 Like

Successfully finished on the first iteration

local function GetPlayerNames()
	local players = Players:GetChildren()
	local name = nil
	for _, v in pairs(players) do
		if v:IsA("Player") then
			name = tostring(v.Name)
		end
	end
	return name
end

local function GetPlayersBodyParts(t)
	local torso = t
	if torso then
		local figure = torso.Parent
		for _, v in pairs(figure:GetChildren()) do
			if v:IsA("Part") then
				return v.Name
			end
		end
	else
		return "HumanoidRootPart"
	end
end

local function GetTorso(part)
	local chars = Workspaces:GetChildren()
	local torso = nil
	for _, v in pairs(chars) do
		if v:IsA("Model") and v ~= script.Parent and v.Name == GetPlayerNames() then
			local charRoot = v:FindFirstChild("HumanoidRootPart")
			if (charRoot.Position - part).magnitude < SearchDistance then
				torso = charRoot
			end
		end
	end
	return torso
end

for _, zambieparts in pairs(ai:GetChildren()) do
	if zambieparts:IsA("Part") then
		zambieparts.Touched:connect(function(p)
			if p.Parent.Name == GetPlayerNames() and p.Parent.Name ~= ai.Name then 
				local enemy = p.Parent
				local enemyhuman = getHumanoid(enemy)
				enemyhuman:TakeDamage(aiDamage)
			end
		end)
	end
end

local path
local waypoint
local oldpoints
local isWandering = 0

if canWander then
	spawn(function()
		while isWandering == 0 do
			isWandering = 1
			local desgx, desgz = hroot.Position.x + math.random(-WanderX, WanderX), hroot.Position.z + math.random(-WanderZ, WanderZ)
			human:MoveTo( Vector3.new(desgx, 0, desgz) )
			wait(math.random(4, 6))
			isWandering = 0
		end
	end)
end

local function checkw(t)
	local ci = 3
	if ci > #t then
		ci = 3
	end
	if t[ci] == nil and ci < #t then
		repeat
			ci = ci + 1
			wait()
		until t[ci]
		return Vector3.new(1, 0, 0) + t[ci]
	else
		ci = 3
		return t[ci]
	end
end

while wait() do
	local enemytorso = GetTorso(hroot.Position)	
	if enemytorso then 
		isWandering = 1

		local path = PathfindingService:CreatePath{
			Costs = {}
		}

		path:ComputeAsync(hroot.Position, enemytorso.Position)

		if path.Status == Enum.PathStatus.Success then
			waypoint = path:GetWaypoints()
			oldpoints = waypoint
			local connection = nil

			local direct = Vector3.FromNormalId(Enum.NormalId.Front)
			local ncf = hroot.CFrame * CFrame.new(direct)
			direct = ncf.p.unit
			local rootr = Ray.new(hroot.Position, direct)
			local phit, ppos = Workspaces:FindPartOnRay(rootr, hroot)

			if path and waypoint or checkw(waypoint) then
				if checkw(waypoint) and checkw(waypoint).Action == Enum.PathWaypointAction.Walk then
					human:MoveTo(checkw(waypoint).Position)
					human.Jump = false
				end
				if checkw(waypoint) and checkw(waypoint).Action == Enum.PathWaypointAction.Jump then
					human:MoveTo(checkw(waypoint).Position)
					human.Jump = true
				end
			end

			if connection then
				connection:Disconnect()
			end
		else
			for i = 3, #oldpoints do
				human:MoveTo( oldpoints[i].Position )	
			end
		end
	elseif enemytorso == nil and canWander then
		isWandering = 0
		path = nil
		waypoint = nil
		human.MoveToFinished:Wait()
	end
end

The code had an error where if there was no enemy to chase, the zombie would not wander. This has been fixed by adding an elseif statement that checks if there is no enemy and if the zombie is allowed to wander.

1 Like