I’ve got a game with 1m+ lines of code. After careful consideration, I’ve decided I want to change the behaviour of ALL Unity Event functions to run in a try/catch, rather than letting them throw an NRE.
So if I have the following code in Duck.cs:
using UnityEngine;
public class Duck : MonoBehaviour
{
void Start() {
throw new NullReferenceException();
}
}
I want to leave that code unmodified, but instead to modify the caller of Start() to be something like
Well, your question seems a bit weird. Those callbacks are called by Unity from the native C++ side. Exceptions can only be caught by the invoker and that’s what Unity does. It actually swallows all exceptions thrown in such an event and creates a log message if that happens. You said you want to handle those exceptions yourself which begs the question: Where do you think you would handled those exceptions if you don’t put a try catch block inside the method?
That’s just not possible. You are not the caller and you can’t modify any of that code as the call actually originates from the C++ runtime. What exactly would a general purpose exception handler actually do? If an exception occurs inside Start for example, the Start method can not continue anyways. What would such a handler actually do? The callback can not continue anyways. How would you distinguish different classes / methods?
I suspect you just want to close your eyes and block your ears and just make it continue without causing a crash on iOS or similar platform? If that’s the case, it would be the wrong approach. Exceptions should not be used as flow control mechanism. They are exceptional cases that indicate an error, always. You should do all you can to avoid exceptions in the first place. Yes, seperate frameworks may throw exceptions to indicate issues they can not handle themselfs but the compounding system may know how to handle those issues. However in this case we have a clear seperation of the two systems. Within your own system you should not rely on exceptions to communicate errors.
1m lines of code and all event method calls should be in try/catch - why?
It‘s your job to find and fix the nullrefs, not to ignore them in hopes everything else will continue just fine.
Worst case scenario: you end up with even worse issues than you have now AND terrible performance due to all those caught exceptions every frame.
This is pretty much what I want to do, so iOS behaves the same way as Android (while logging the exception manually so it can still be fixed). However, given the information you mentioned with the runtime, it doesn’t seem like I can do this.
I’m going to write a script that changes all my code to put the event functions in a try-catch. I’ll share the code here when I’m done in case anyone finds this thread from Google and wants to do something similar.
This is just asking for trouble, should fix the issues with your code as you find them, not just sweep it under the rug. If something goes so wrong it throws a exception yeah i want it to blow up, and toss a nice stack trace my way so the problem is obvious and can be fixed.
I understand where you’re coming from and won’t try to change your mind, but I check and fix all exceptions in Crashlytics and Unity Dashboard after each release. Sometimes edge cases slip through, and given Android doesn’t crash, I’d rather iOS just not crash either (since crashes tend to cause a drop in revenue, and I’m no longer doing Unity as a side hobby - stakes are a bit higher now). If there isn’t a “good” way to handle this in Unity, I don’t really see anything wrong with running a linter to change all my event functions to try/catch. I’ll take the (minimal) performance hit.
If 3 years of Android not exiting on exception has been fine, I’m not worried about making iOS act the same way
Also if its full crashes, you might want to look into your IOS player settings and Script Call Optimization and set it to “Slow and Safe”. I been working with Unity professionally for 10 years now mostly in the mobile space, and do not get full crashes from exceptions.