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

Variable is nil, and I can't figure out why?

Asked by 5 years ago

So I have this NPC, and it works, unless you walk behind it or around it. I get the error 'Workspace.NewNpc.Dummy.AI:94: attempt to index global 'prs' (a nil value)'.

The script's really long, sorry if this hurts your eyes.

``` local ts = game:GetService("TweenService")

local event = Instance.new("BindableEvent")

event.Name = ("StartAttacking")

event.Parent = script.Parent.Parent

wait(5)

script.Parent.AttackingPlayer.Value = ""

local range = 20

local function searchforplayer()

local ray = Ray.new(script.Parent.HumanoidRootPart.CFrame.Position, script.Parent.HumanoidRootPart.CFrame.LookVector * 500)

local hrp = script.Parent.HumanoidRootPart.Position

local num = 8

local part = game.Workspace:FindPartOnRay(ray)

local person = nil

if part then

if part.Parent:FindFirstChild("Humanoid") then

if game.Players:FindFirstChild(part.Parent.Name) then

print("Found player!")

print(part.Parent.Name)

person = part.Parent

end

end

end

if person == nil then

local region = Region3.new(Vector3.new(hrp.X - num, hrp.Y - num, hrp.Z - num), Vector3.new(hrp.X + num, hrp.Y + num, hrp.Z + num))

local parts = game.Workspace:FindPartsInRegion3(region)

for a, b in pairs(parts) do

if b.Name == ("HumanoidRootPart") then

print(b.Name)

person = b.Parent

end

end

else

return person()

end

if person ~= nil then

return person

end

end

while true do

if script.Parent.AttackingPlayer.Value == "" then

print("Searching...")

if searchforplayer() == nil then

while searchforplayer() == nil do

wait(0.1)

if searchforplayer() ~= nil then

script.Parent.AttackingPlayer.Value = searchforplayer().Name

script.Parent.Head["!Gui"].Frame.TextLabel.Visible = true

script.Parent.Humanoid.JumpPower = 48

script.Parent.Humanoid.Jump = true

wait(1)

script.Parent.Head["!Gui"].Frame.TextLabel.Visible = false

script.Parent.Humanoid.JumpPower = 0

break

end

end

end

end

local path = game:GetService("PathfindingService"):CreatePath()

if script.Parent.AttackingPlayer.Value ~= ("") then

local prs = game.Workspace:FindFirstChild(script.Parent.AttackingPlayer.Value)

end

if script.Parent.AttackingPlayer.Value ~= ("") then

event:Fire(script.Parent.AttackingPlayer.Value)

end

range = math.huge

path:ComputeAsync(script.Parent.HumanoidRootPart.Position, prs.HumanoidRootPart.Position)

local points = path:GetWaypoints()

local player = game.Workspace:FindFirstChild(script.Parent.AttackingPlayer.Value)

script.Parent.Parent.Points:ClearAllChildren()

for a, b in pairs(points) do

part = Instance.new("Part")

part.CanCollide = false

part.Size = Vector3.new(1,1,1)

part.Position = b.Position

part.Anchored = true

part.Transparency = 1

part.Parent = script.Parent.Parent.Points

end

if path.Status == Enum.PathStatus.Success then

for a, b in pairs(points) do

script.Parent.Humanoid:MoveTo(part.Position)

if b.Action == Enum.PathWaypointAction.Jump then

script.Parent.Humanoid.Jump = true

end

end

end

end ```

I get this error if I stand in front of the guy, or be around him. Any help?

2 answers

Log in to vote
0
Answered by 5 years ago

Using :FindFirstChild() does not always return something. Before calculating a path, check to see if prs exists.

if prs then
    -- Code for pathfinding
end
Ad
Log in to vote
0
Answered by 5 years ago

When you say that a variable is local, it only exists in the scope you define it. In other words, because you define local prs in the if block, prs does not exist outside of that if block! prs will never be a non-nil value. To fix this, specify that prs is local outside the if statement, in the same scope that you later use it: lua local prs if script.Parent.AttackingPlayer.Value ~= ("") then prs = game.Workspace:FindFirstChild(script.Parent.AttackingPlayer.Value) end SaltyIceberg is correct that you must also check to see if prs is non-nil.

Some other problems with this script: - return person() will fail, since person is not a function. Right after that, you have if person ~= nil then return person end, which makes the return person() redundant (in addition to being incorrect). Remove the else return person() part. - You have if searchforplayer() == nil then followed by while searchforplayer() == nil then, but you can just remove the if staement (along with the corresponding end) since while will not run its code even once if the condition is false - You should try to avoid running functions (especially ones that are complicated) more than necessary. You can save the result of calling searchforplayer() to a variable so you can access the player's name: lua if script.Parent.AttackingPlayer.Value == "" then print("Searching...") local player while true do player = searchforplayer() if player then break end wait(0.1) end script.Parent.AttackingPlayer.Value = player.Name script.Parent.Head["!Gui"].Frame.TextLabel.Visible = true script.Parent.Humanoid.JumpPower = 48 script.Parent.Humanoid.Jump = true wait(1) script.Parent.Head["!Gui"].Frame.TextLabel.Visible = false script.Parent.Humanoid.JumpPower = 0 end - if script.Parent.AttackingPlayer.Value ~= ("") then makes no sense because the code before it guarantees that AttackingPlayer will exist - range = math.huge could just be set once at the top of the script (where it currently says local range = 20) - You should assign AttackingPlayer to a local variable instead of saying script.Parent.AttackingPlayer every time - prs.HumanoidRootPart might not exist if the player (for instance) fell off the edge of the map; you should use FindFirstChild there - No point in having both prs and player both point to the player's character model (rename prs to player and remove the repetition) - When having the NPC follow the pathfinding result: - You don't want to use pairs, or else it'll attempt to follow the path out of order! - You don't have the script wait until the NPC actually gets to the checkpoint, you just tell it to start moving towards each checkpoint. You need to either have a loop where you wait until the NPC stops moving and/or gets close to its target.

Aside from the last point, I fixed the above in the following: ```lua local ts = game:GetService("TweenService") local event = Instance.new("BindableEvent") event.Name = ("StartAttacking") event.Parent = script.Parent.Parent

wait(5)

local attackingPlayer = script.Parent.AttackingPlayer
attackingPlayer.Value = ""

local range = math.huge

local function searchforplayer() local ray = Ray.new(script.Parent.HumanoidRootPart.CFrame.Position, script.Parent.HumanoidRootPart.CFrame.LookVector * 500) local hrp = script.Parent.HumanoidRootPart.Position local num = 8 local part = game.Workspace:FindPartOnRay(ray) local person = nil if part then if part.Parent:FindFirstChild("Humanoid") then if game.Players:FindFirstChild(part.Parent.Name) then print("Found player!") print(part.Parent.Name) person = part.Parent end end end if person == nil then local region = Region3.new(Vector3.new(hrp.X - num, hrp.Y - num, hrp.Z - num), Vector3.new(hrp.X + num, hrp.Y + num, hrp.Z + num)) local parts = game.Workspace:FindPartsInRegion3(region) for a, b in pairs(parts) do if b.Name == ("HumanoidRootPart") then print(b.Name) person = b.Parent end end end if person then return person end end

while true do if attackingPlayer.Value == "" then print("Searching...") local player while true do player = searchforplayer() if player then break end wait(0.1) end attackingPlayer.Value = player.Name script.Parent.Head["!Gui"].Frame.TextLabel.Visible = true script.Parent.Humanoid.JumpPower = 48 script.Parent.Humanoid.Jump = true wait(1) script.Parent.Head["!Gui"].Frame.TextLabel.Visible = false script.Parent.Humanoid.JumpPower = 0 end local path = game:GetService("PathfindingService"):CreatePath() local player = game.Workspace:FindFirstChild(attackingPlayer.Value) event:Fire(attackingPlayer.Value) local playerHRP = prs:FindFirstChild("HumanoidRootPart") if playerHRP then path:ComputeAsync(script.Parent.HumanoidRootPart.Position, playerHRP.Position) local points = path:GetWaypoints() script.Parent.Parent.Points:ClearAllChildren() for a, b in pairs(points) do part = Instance.new("Part") part.CanCollide = false part.Size = Vector3.new(1,1,1) part.Position = b.Position part.Anchored = true part.Transparency = 1 part.Parent = script.Parent.Parent.Points end if path.Status == Enum.PathStatus.Success then for a, b in ipairs(points) do script.Parent.Humanoid:MoveTo(part.Position) if b.Action == Enum.PathWaypointAction.Jump then script.Parent.Humanoid.Jump = true end end end end end ```

Answer this question