Is Using PCalls Like this right?

I made a Mini Games type of game. The structure is this.

  1. All the maps (games) are in ServerStorage, and have a “MapScript” inside them.
  2. A map gets chosen, the mapscript from it gets cloned to serverscriptservice and the game is executed.

Here’s how mapscript is structured:

  1. Doing a bunch of stuff, teleporting players, starting the specific game.
  2. Starting a timer after which the game will end
3. Destroying the map and firing bindable event to choose next map.

Now it is very important that these mapscripts work without an error, because if there’s even a tiny error, the whole game will stop and no new maps will be chosen. I made my best to prevent errors by using if findfirstchild statements, and so far I didn’t meet any error during testing.

But better safe than sorry, so I want to do this.

local success, err = Pcall(function()
1. Doing a bunch of stuff, teleporting players, starting the specific game.
2. Starting a timer after which the game will end
end)

3. Destroying the map and firing bindable event to choose next map.

I want to do this, so that even if there is an error, the next map gets chosen and the whole game doesn’t stop.

I tried this already with one map, and it worked with no errors, then I purposefully made it error inside pcall, and again, as intended, it destroyed the error map and chose the next one. So it’s working.

My question is
Is there anything wrong with this, or something that I should consider?

This is my first time using pcalls, that’s why I need your advice. Thanks in advance.

1 Like

“Better safe than sorry” already tells me that technically you aren’t using them correctly. If you need to pcall everything to ensure your game doesn’t break, then you need to look at your code and solve specific problems. For instance, if you are teleporting players, check if player.Character and player.Character.PrimaryPart exists before calling :SetPrimaryPartCFrame, which will prevent some errors there. Checks like these will prevent the majority of common errors from occurring.

Now that that’s said, personally, I don’t really see why doing it your way would really matter. It is especially helpful to have your code wraps in pcalls if you are catching the errors and recording them. This way, the gameplay can continue and you can still locate the problem. However, a downside to wrapping large chunks of code in a pcall is if an error occurs early on, the rest of the code will not execute. Because of this, it is better to isolate parts of your code that really need a pcall (for whatever reason if you can’t find a solution to the errors occuring), that way all of your code doesn’t have the potential of never executing.

Extra info: The only reasons I use pcalls these days is if I am attempting to access something like DataStores, MarketplaceService, Http Requests, etc. as these may fail due to server outages, internal errors, etc. (on top of that, I will also use them to find errors in specific parts of code, but they will not remain in said code when the game is released). I would say this is probably the best practice for pcalls.

4 Likes

I think in this instance it would be advisable for each round to have an individual script waiting to be triggered. That way rounds can continue and you can still collect errors properly, and you don’t need pcall.

1 Like

It would help if your statements made any sense at all.

I already mentioned in the post, that I am using if statements like that, and so far no error have occurred on any of the maps without pcalls. You obviously didn’t understand the point of my question.

Thank you, you were not helpful at all.

Maybe instead of being hostile towards someone just trying to provide you with a complete set of information, you could take away information from this last section of my reply. Though I didn’t directly say it, but pcalls really should only be used for debugging and requests to external API. Here is a link to another post that is pretty much asking the same question in a different way than you that you should consider reading the replies to: Is it ok to pcall unstable code?

1 Like

I just did, same nonsense replies

“You’re running away from your problems instead of confronting them directly.”

For the last time (third time’s the charm). After testing my code for 2+ months, there have been no errors in any of my maps, I am using if statements that prevent erroring. The problem is in 200+ lines of code you can never be 100% sure that there won’t be an error, and even the smallest insignificant error will break my game server entirely, and it will require a restart, hence the need to use pcalls.

“If the error stops a queue, irregardless of the pcall, it will still stop the queue.”

Also completely untrue, as mentioned in my post, when wrapped in a pcall, I inserted an intentional error, and the game didn’t break, it destroyed the map and started the next map.

I am not being hostile to anyone, I am pointing out that you are giving answer that makes no sense and doesn’t adress the issue in the topic properly.

Okay, how do you want us to address the issue to the topic properly? No, using pcalls like that is not right. That is not the intended use. If you really want to use pcalls because it makes you feel better or whatever it’s not going to cause any issues, but the correct method of doing it would be to have each maps code in a module, then require that module. If the module errors, log the error and move on with your day.

local recordedErrors = {}

function module:Error()
	if (not table.find(recordedErrors,self)) then
		table.insert(recordedErrors,self)
	end
end

function module:LoadMap()
	local success, err = pcall(function()
		require(script[self])
	end)
	if (err) then
		module.Error(err)
	end
end
2 Likes

You finally did address it properly, when you answered the question, instead of making bunch of non related statements.

This

And this

Are what I needed.
Tho I still do not agree with your absurd claim that

Anything to back this up? Isn’t preventing errors the purpose of pcalls? Who’s intended, where it says that this is not the intended use, or that there is only a very specific cases in which it is intended to be used?

It is like when people say “You have to do this”, you ask “Why”, and the only answer they can give is “Just because”.

pcall()s have a signficant impact on performance and overhead and thus should be used sparingly, their purpose is to handle code which is prone to errors, i.e; API methods that rely on the network. You shouldn’t be using pcall()s to handle logic errors in your code. Treat pcall() as a failsafe/fallback for handling errors that you otherwise have no control over, this does not include the operations you described.

5 Likes

The ONLY time at which you must use pcall() is when it’s not your problem, but a server error. For example any function that has ASync in it’s name or other functions that you can’t access the code of and they fail because of a server error. Usually that’s it and you shouldn’t use pcall() for anything else. Otherwise it’s bad practice. You can always yield, branch code or summon a thread to fix an issue without needing to wrap it into a pcall().

I am not giving in on bad practices, so I very rarely use pcall() wraps outide of intended use. For example I make a GUI, it has buttons that lead to other GUIs, but they aren’t done. I make a comment --unwrap from pcall() when done with the rest of the GUIs and it’s better for my case than making an if gui exists then open it. It’s because usually my button opening scripts look like this:

for _, button in ipairs(buttonFrame:GetChildren()) do
    button.Activated:Connect(function()
        -- unwrap from pcall() when done with the rest of the GUIs
        pcall(function()
            playerGui[button:GetAttribute("GuiToOpen")].Enabled = true
            button.Parent.Parent.Enabled = false
        end)
    end)
end

pcalls are not a solution for unreliable code, they block error handling unless you use them properly, and it makes debugging the worst experience of all time