Best method to avoid Game Errors from Characters Leaving?

I have been coding games for over 10 years, and to this day, I find out that some code in my main game loop can break due to characters no longer existing while within a if Player.Character then statement. Obviously code takes time to execute, so anything within that statement becomes subject to the original statement no longer being true.

Line 94, the original statement to make sure the Character exists

The error, line 118 (after it had already executed the same if statement on line 114) The error implying the player left in-between these if statements running; therefore, plr.Character is no longer a valid object to refer to, thus breaking the FindFirstChild call.

I could make a if plr.Character statement each and every time I try to reference it.
I could wrap this in a spawn to avoid it stopping the break from killing the entire game loop, as this is a module attached to the game loop, however, I’d like to see if there’s any other solutions. What do you think?

1 Like

In this situation I would recommend using pcall() in order to handle the errors if they occur. This way, you would not have an errors, and you would not have to use a spawn statement. Also, you could reformat your if statements to look like:

    if plr.Character and plr.Character:FindFirstChild("Whatever") then 
    
    end
1 Like

Yeah, good confirmation thanks. Just changed to do this every single time, quite peculiar

1 Like

Define the character at the top of the function.

local character = plr.Character

if character then
    local jetpackTool = character:FindFirstChild("JetpackTool")
    if jetpackTool then
        -- Do your thing
    end
end

I am assuming all of these objects that you are :Destroy()ing are tool objects, and of course a character can only have one tool parented to it at a time, meaning you don’t necessarily have to check for each object, just :Destroy() the first plr.Character:FindFirstChildOfClass("Tool").
As for the message to pass to .AwardBadge(), it can be simply achieved using some string manipulating, and I also assume that this is the reason why you did the if statements in the first place. You would need an if statement to check if the object’s name is UltimatePath since that doesn’t get awarded a badge for.

if plr.Character then
    local tool = plr.Character:FindFirstChildOfClass("Tool")
    if tool then
        if tool.Name ~= "UltimatePath" then
            BadgeAwardModule.AwardBadge(plr, "Badge"..tool.Name:gsub("Tool", "").."Survive")
        end
        tool:Destroy()
    end
end

This is surely guaranteed to not error, since there is no way a player would leave between these two lines
image
and plr.Character is not used anywhere else. Only problem I would think of is .AwardBadge causing issues if the player left before the program’s flow got there.

1 Like