THUNGSTEN Tools The GameDev Blog

Proper Debug Logging in Unity

How to properly setup your custom logging system.

As soon as you go beyond using Debug.Log everywhere and instead integrate it into your own logging system, there's a few things you should know to improve your experience.

Unity's built-in Debug.Log is fine for small projects, but as soon as you want real control (storing logs elsewhere, filtering them, or shipping different behavior between dev and release) you quickly run into problems. Two in particular:

  1. Click Redirect: Clicking a log message in the Console takes you to Unity's internal Debug.Log, not the line in your own code that triggered it.
  2. Stack Trace Lines: Unity includes extra call frames from your wrapper methods, cluttering the output.

Both issues break the point of having a custom logger: you lose accuracy when navigating errors and waste time parsing noise in stack traces. Let's fix that.

Disclaimer

These solutions have been tested on Unity 6.0+. They are expected to work in older versions, but behavior may vary. Always validate in your target Unity version.

Why bother with a custom logging system?

A controlled logging pipeline gives you options Unity's default logger does not:

Unity's built-in logger is global and opaque. Owning the pipeline makes it modular and testable like any other system in your game.

1. Fixing Click Redirect

By default, double-clicking a log opens Unity's internal Debug.Log call, not your code. Unity's Console looks for specific naming patterns to decide where to jump. If your class and method don't follow these patterns, you will never land on the right line.

Class naming rules

The class containing your log methods must end with "Logger". Unity uses this suffix to resolve click targets.

Valid:

Invalid:

Method naming rules

Logging methods must start with "Log". Anything else will be ignored by Unity's redirection logic.

Valid:

Invalid:

2. Removing Extra Stack Trace Lines

Without adjustment, Unity includes your logger's method frames in every stack trace, burying the actual caller deeper in the log. This is avoidable.

Enable Strip Logging Callstack

In the Unity Editor, open the Console settings (ellipsis button, top right) and enable Strip logging callstack. This removes redundant frames from the Console view.

The Unity Editor console options.
Unity Editor console options, opened by clicking the small ellipsis button on the top right of the console.

Mark helper methods with HideInCallstack

On every logger method you don't want polluting stack traces, add the [HideInCallstack] attribute. Place it directly above the method declaration:

Complete Example: Custom Logger

With both fixes applied, here is a functional base logger that routes messages through your system while maintaining clean Console navigation and stack traces:


public enum LogLevel
{
    Info, Warning, Error
}

public static class CustomLogger
{
    [HideInCallstack]
    public static void Log(
        object message, 
        LogLevel level = LogLevel.Info, 
        bool unityLog = true)
    {
        // Example extension points:
        // - Write to a custom file or rolling buffer
        // - Send JSON to a remote debugging service
        // - Forward logs to analytics
        
        if (unityLog)
        {
            switch (level)
            {
                case LogLevel.Info:
                    Debug.Log(message); break;
                case LogLevel.Warning:
                    Debug.LogWarning(message); break;
                case LogLevel.Error:
                    Debug.LogError(message); break;
            }
        }
    }
}

Usage


// Defaults to LogLevel.Info (Debug.Log)
CustomLogger.Log("Enemy hit!");

// Explicit LogLevel.Error (Debug.LogError)
CustomLogger.Log("Enemy died even though it was immune!", LogLevel.Error);

// Custom processing only, no Unity log
CustomLogger.Log("Background sync completed.", unityLog: false);

Result

With Strip logging callstack enabled and [HideInCallstack] applied, Unity no longer shows CustomLogger:Log(...) in the stack trace. Double-clicking Console entries takes you directly to the line of code that called the logger. You get the flexibility of a custom pipeline without losing the precision of Unity's debugging tools.

This setup is the minimum baseline. From here you can extend it into structured logging, asynchronous log handling, or integration with monitoring dashboards.

That's all there is to it. Happy debugging out there!