1
\$\begingroup\$

Do errors that come up in the Unity editor affect a game's performance on a device (on Android in particular)? I'm talking about errors that keep coming continuously during Update() such as NullReferenceException and "Debug.Log".

\$\endgroup\$
3
  • \$\begingroup\$ What kind of errors ? For instace the Debug.Log(not a error per say) will run on the device too and if happen to be logging every frame that could affect performance . \$\endgroup\$
    – Uri Popov
    Jun 30 '16 at 8:29
  • \$\begingroup\$ @UriPopov I edited the question. I didn't know that Debug.Log could affect performance! Thanks for the information. \$\endgroup\$
    – Amn
    Jun 30 '16 at 8:31
  • 5
    \$\begingroup\$ You shouldn't worry about this stuff, and instead fix the errors. You shouldn't release andor test games that error continuously. \$\endgroup\$
    – user35344
    Jun 30 '16 at 8:37
4
\$\begingroup\$

Here are my tips for how to handle errors before release.

Tip.1: If your game is trowing NullReferenceException's during runtime. Fix them. Fix all of them. Note your game will still do this because it is nay impossible to test everything before the users get their dirty little hands on the game.

Tip.2 Wrap your Debug.anythings in if(Debug.isDebugBuild) that way you dont have to bother removing all of them when you release.

Tip.3 I generally dont worry about warnings (still a good idea to fix them) and I'm 90% sure they dont effect performance.

Tip.4 if you have Debug stuff in any Update() method just remove it from the build. Update() is called once per frame and you want to keep it as clean as possible. Then again with the power of today's devices a couple more if's wont do anything noticeable but is's just a good practice.

\$\endgroup\$
4
  • \$\begingroup\$ Thanks for the answer. Can you explain this: "Note your game will still do this because it is nay impossible to test everything before the users get their dirty little hands on the game." \$\endgroup\$
    – Amn
    Jun 30 '16 at 8:43
  • 2
    \$\begingroup\$ I mean no mater how much you test, bug fix, refactor the code and so on your game will have bugs when you release it. Unless its a rather simple game with only one or two states it will have cases that you did not test and did not fix before release. Think of Skyrim as the perfect example. On release there were tons of bugs. \$\endgroup\$
    – Uri Popov
    Jun 30 '16 at 8:47
  • 1
    \$\begingroup\$ The dont worry about warnings bit seems like a slippery path to some very questionable coding practices \$\endgroup\$
    – Niels
    Jun 30 '16 at 12:51
  • \$\begingroup\$ He wasn't asking about coding practices he was asking about what affects performance. Specific questions specific answers. \$\endgroup\$
    – Uri Popov
    Jun 30 '16 at 13:36
4
\$\begingroup\$

Null Reference Exception

A NullReferenceException is a runtime exception that happens when you haven't set a variable to an instance of an object, and then attempt to use that object. For example, the following could cause a NullReferenceException if TestObj isn't set

using UnityEngine;

public class NullTest : MonoBehaviour
{
    public GameObject TestObj;

    void Update()
    {
        // This throws an Exception
        TestObj.transform.position = new Vector3();

        // This line won't get called
        Debug.Log("Won't get here");
    }
}

While this doesn't come with a performance hit that I'm aware of, you are forcing Unity to catch the exception. In a normal application the NullReferenceException would stop the program and the user could not continue, but Unity catches that exception and carries on, which can lead to odd game behaviour.

A good approach is to use defensive programming to ensure that you get as few errors as humanly possible. It's worth pointing out that it's easy to go overboard with null checks (one early mistake a lot of people make is to put them everywhere), so keep the check to things you can't control yourself (i.e. public MonoBehaviour properties, GetComponent calls etc).

In our (very simple) example above, a defensive approach could be:

using UnityEngine;

public class NullTest : MonoBehaviour
{
    public GameObject TestObj;

    void Update()
    {
        // Avoid an exception by testing that TestObj is not null
        if (TestObj != null) {
            TestObj.transform.position = new Vector3();
        }

        // This line will now get called
        Debug.Log("Gets here");
    }
}

Or, if TestObj was integral to the Update (e.g. it's used quite a bit throughout the method), you could simply exit the Update. Note the #if UNITY_EDITOR here, which is a preprocessor directive so that the Debug.LogError doesn't get built into your live build

using UnityEngine;

public class NullTest : MonoBehaviour
{
    public GameObject TestObj;

    void Update()
    {
        // Avoid an exception by exiting from Update if TestObj is null
        if (TestObj == null) {
            // Optionally log your error
            #if UNITY_EDITOR
                 Debug.LogError("TestObj is not set");
            #endif

            // Exit the update
            return;
        }

        TestObj.transform.position = new Vector3();

        // This line will now get called
        Debug.Log("Gets here");
    }
}

Debug.Log

Debug.Log, on the other hand, is incredibly resource heavy, especially when called in an Update. Really your build shouldn't contain any Debug messages so you should aim to remove them where possible. As @uri-popov says in their answer, you can use Debug.isDebugBuild to stop these messages appearing on release.

However, a better approach may be to use preprocessor directives to stop your Debugs from ever even being compiled into your release. This works by telling the compiler to skip over the lines of code that aren't applicable, so that your release build never has to do a check to see if it's in debug mode as it's done at compile time.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Being defensive with null checks is rarely a good thing. One or two throughout your codebase may be tolerable, but be wary of making them a habit \$\endgroup\$
    – blgt
    Jun 30 '16 at 14:24
  • \$\begingroup\$ I think really it depends on where you're being defensive. Because Unity is component based checking that your public variables aren't null is an absolute must, as forgetting to set them in the editor is all too easy to do (and will cause odd behaviour if you don't). For methods that take parameters etc, you can afford to be less defensive and have a little trust in your code (so long as that code isn't being distributed as a third party library). Really, it's all about finding the balance between what is good practise and works, and what's practical :-) \$\endgroup\$
    – hobnob
    Jun 30 '16 at 14:34
  • \$\begingroup\$ Updated the answer so that it explains how best to use defensive programming a bit better \$\endgroup\$
    – hobnob
    Jun 30 '16 at 15:51
1
\$\begingroup\$

These kinds of errors are exceptions which abort your functions in unintended ways.

As such they can speed up or slow down the execution of your game (by skipping vital pieces of code), but the question about speed it the wrong question in this situation.

Fix the code.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .