I have a modulescript with a bunch of functions that the game accesses. during gameplay I noticed that functions will error when a part becomes nil. this will continue even if I check if a part still exists. the function would check if a model exists then quickly index something in it only to error as the model becomes nil right when its being indexed. my idea of a solution to this is to just pcall the function.
I tried this one way but found that when added the function does not work at all. here is an example:
module.getclosestnpc = function(model,cs,range)
pcall(function()
local mag
local closest
local closestnum = 1000000000
for _, p in pairs(cs:GetTagged("BotNpcs")) do
if model and model.PrimaryPart then
local mag = (model.PrimaryPart.Position - p.PrimaryPart.Position).Magnitude
if mag <= range and mag < closestnum and
model:FindFirstChild("AICore") and model.AICore.TeamID.Value ~= p.AICore.TeamID.Value and p.Humanoid.Health > 0 or
mag <= range and mag < closestnum and model:FindFirstChild("Health") and model:FindFirstChild("Active") and model.Parent.TeamID.Value ~= p.AICore.TeamID.Value and p.Humanoid.Health > 0 then
closestnum = mag
closest = p
end
end
end
return closest
end)
end
having the pcall were its at causes the function to not work at all but if I remove it, the script works but will error as mentioned above. should I be using pcall in a modulescript and if so were should it go?
also, an example error would be "attempting to index nil (model.PrimaryPart) with position, which is the line were the value “mag” is made.
This is the opposite of what pcall is meant to be used for. Apart from being very expensive to use, it’s meant for errors that happen outside of your control (usually web-related stuff). You should fix your code rather than wrapping pcall around it.
The error is saying there might not be a PrimaryPart on all of your models so you should set the PrimaryPart of your model when you create it/clone it.
the primary part is set, however when this function runs the model may suddenly become nil, which means the primarypart no longer exists. this is hardly a coding problem and I did try checking if it exists first.
model cannot become nil unless you specifically set it to nil. While the reference might become invalid when you destroy the object, it’ll still point to the object. That’s why memory leaks happen. There is no way model can become nil.
the value model that we are referring to is an npc. this npc will “delete” itself after it dies, this means the model no longer exists. this supposedly is what the problem is as its trying to index nil (the models primarypart) with position. and because of this I needed pcall which catches errors and lets the script continue to run.
No, this is not the problem. You’ll see the behavior I mentioned earlier if you run this demo.
local a = Instance.new("Part")
a:Destroy()
print(a) -- Will print the object as it still exists
EDIT: Because of this, I know the issue can’t possibly be what you think it is. I’m entirely confused on how you got this error to begin with since you check if there’s a PrimaryPart set.
EDIT2: Would you mind showing me the full error message so I can see which line the error occurs on as well as the error?
EDIT3: My theory is that the problem is being caused by p, rather than model since model is checked while p is not.
local a = game.Workspace.TestPart
wait(3)
local newpart = Instance.new("Part")
newpart.Parent = game.Workspace
newpart.Position = game.Workspace.TestPart
delete testpart within 3 seconds and it throws an error
this is more simular to what is going on, but much quicker.
edit: also, you are right about one thing, p is the npc, which is the part that becomes nil.
I apologize for saying model was the npc but the main issue remains as it still is trying to compare the npcs primarypart with models primarypart on the line were magnitude is made.
As you can see, it still works. The only reason your code ran into an error is because it indexed workspace to get TestPart again instead of using a (your reference to TestPart).
local a = game.Workspace.TestPart
print("waiting")
wait(10)
print("running code now")
local newpart = Instance.new("Part")
newpart.Anchored = true
newpart.Color = Color3.new(1,0,0)
newpart.Parent = game.Workspace
newpart.Position = a.Position
Since p is the issue, simply check it just like you’re currently checking the model so that the code works fine.
if model and model.PrimaryPart and p and p.PrimaryPart
EDIT: I would recommend checking if model exists and if model has a PrimaryPart outside of the for loop because you don’t need to perform this check more than once.
module.getclosestnpc = function(model,cs,range)
local mag
local closest
local closestnum = 1000000000
for _, p in pairs(cs:GetTagged("BotNpcs")) do
if model and model.PrimaryPart and p and p.PrimaryPart then
local mag = (model.PrimaryPart.Position - p.PrimaryPart.Position).Magnitude
if mag <= range and mag < closestnum and
model:FindFirstChild("AICore") and model.AICore.TeamID.Value ~= p.AICore.TeamID.Value and p.Humanoid.Health > 0 or
mag <= range and mag < closestnum and model:FindFirstChild("Health") and model:FindFirstChild("Active") and model.Parent.TeamID.Value ~= p.AICore.TeamID.Value and p.Humanoid.Health > 0 then
closestnum = mag
closest = p
end
end
end
return closest
end
Yeah, that should stop the code from running into an error. However, not all of the npcs might work for this since it seems like some of them don’t have their PrimaryPart set. I would recommend setting their PrimaryPart wherever you’re creating them.
Yeah, that’s what I figured too but it’s weird that error would happen then unless something else is setting the PrimaryPart to nil. Let me know if you figure out why it’s happening because I’m interested.
I had to write the errors down in game on notepad during a playthrough with a friend. the error caused all the turrets to stop firing. the errors occured in the modulescript which I assume stopped the script it from working which broke the game. If I find the cause Ill be sure to share it with you.