Is there any way to view the console in a build?

Hello, I always have issues debugging my multilayer games becuase I don’t know how to view console debug logs and log-errors in a Unity build.

Is there any way to do this? Or simply a way to access existing debug log messages through runtime scripts?

Thanks.

An even simpler way to do it.

Just attach this script to any scene gameObject:

This works perfectly with ANY build (debug, production) and ANY platform.

It shows EXACTLY what you would see on the console (Debug.Log, Debug.Error, errors, crashes etc)

    using UnityEngine;
    
    namespace DebugStuff
    {
        public class ConsoleToGUI : MonoBehaviour
        {
    //#if !UNITY_EDITOR
            static string myLog = "";
            private string output;
            private string stack;
    
            void OnEnable()
            {
                Application.logMessageReceived += Log;
            }
    
            void OnDisable()
            {
                Application.logMessageReceived -= Log;
            }
    
            public void Log(string logString, string stackTrace, LogType type)
            {
                output = logString;
                stack = stackTrace;
                myLog = output + "

" + myLog;
if (myLog.Length > 5000)
{
myLog = myLog.Substring(0, 4000);
}
}

            void OnGUI()
            {
                //if (!Application.isEditor) //Do not display in editor ( or you can use the UNITY_EDITOR macro to also disable the rest)
                {
                    myLog = GUI.TextArea(new Rect(10, 10, Screen.width - 10, Screen.height - 10), myLog);
                }
            }
    //#endif
        }
    }

Here’s another version in which you can

toggle with the space bar

it also creates a full log file anywhere you want (in the example, on the desktop)

it “corrects” the simple GUI window so the text size is always readable on all screens and all platforms

using UnityEngine;

public class ConsoleToGUI : MonoBehaviour
{
    string myLog = "*begin log";
    string filename = "";
    bool doShow = true;
    int kChars = 700;
    void OnEnable() { Application.logMessageReceived += Log; }
    void OnDisable() { Application.logMessageReceived -= Log; }
    void Update() { if (Input.GetKeyDown(KeyCode.Space)) { doShow = !doShow; } }
    public void Log(string logString, string stackTrace, LogType type)
    {
       // for onscreen...
        myLog = myLog + "

" + logString;
if (myLog.Length > kChars) { myLog = myLog.Substring(myLog.Length - kChars); }

        // for the file ...
        if (filename == "")
        {
            string d = System.Environment.GetFolderPath(
               System.Environment.SpecialFolder.Desktop) + "/YOUR_LOGS";
            System.IO.Directory.CreateDirectory(d);
            string r = Random.Range(1000, 9999).ToString();
            filename = d + "/log-" + r + ".txt";
        }
        try { System.IO.File.AppendAllText(filename, logString + "

"); }
catch { }
}

    void OnGUI()
    {
        if (!doShow) { return; }
        GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity,
           new Vector3(Screen.width / 1200.0f, Screen.height / 800.0f, 1.0f));
        GUI.TextArea(new Rect(10, 10, 540, 370), myLog);
    }
}

Obviously, if you prefer to use Unity.UI rather than the legacy “GUI”, it is completely trivial to write it to a UI.Text in your Canvas.

Sorry for necro-ing the post but in Unity 2017.1 you can connect your device to Unity and then look at the log from your computer. I found this better than trying to print the log on your device’s screen. On the downside it prints a bit more than you want (it includes Android system message sometimes, for example.)

An easy way is to set your build to a Development Build (in the build settings) and then use Debug.LogError(). This will show up in the console build.

For standalone builds, the console output is dumped to the file …_Data/output_log.txt It looks a bit more unintuitive than the editor’s console log, since for every message printed, the callstack is also dumped.

Or you could use http://wiki.unity3d.com/index.php/DebugConsole which lets you print normal debug messages (DebugConsole.Log(“…”):wink: in the GUI layer of your game view.

EDIT: for a very convenient way that works in-app on all platforms, see @cybervaldez’ answer

Fortunately nowadays (2020) it is now quite easy to do this

toggle with the space bar

it also creates a full log file anywhere you want (in the example, on the desktop)

it “corrects” the simple GUI window so the text size is always readable on all screens and all platforms

using UnityEngine;

public class ConsoleToGUI : MonoBehaviour
{
    string myLog = "*begin log";
    string filename = "";
    bool doShow = true;
    int kChars = 700;
    void OnEnable() { Application.logMessageReceived += Log; }
    void OnDisable() { Application.logMessageReceived -= Log; }
    void Update() { if (Input.GetKeyDown(KeyCode.Space)) { doShow = !doShow; } }
    public void Log(string logString, string stackTrace, LogType type)
    {
       // for onscreen...
        myLog = myLog + "

" + logString;
if (myLog.Length > kChars) { myLog = myLog.Substring(myLog.Length - kChars); }

        // for the file ...
        if (filename == "")
        {
            string d = System.Environment.GetFolderPath(
               System.Environment.SpecialFolder.Desktop) + "/YOUR_LOGS";
            System.IO.Directory.CreateDirectory(d);
            string r = Random.Range(1000, 9999).ToString();
            filename = d + "/log-" + r + ".txt";
        }
        try { System.IO.File.AppendAllText(filename, logString + "

"); }
catch { }
}

    void OnGUI()
    {
        if (!doShow) { return; }
        GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity,
           new Vector3(Screen.width / 1200.0f, Screen.height / 800.0f, 1.0f));
        GUI.TextArea(new Rect(10, 10, 540, 370), myLog);
    }
}

Obviously, if you prefer to use Unity.UI rather than the legacy “GUI”, it is completely trivial to write it to a UI.Text in your Canvas.

Came looking for this answer, none of these answers are correct, found the correct answer in the uLinkConsoleGUI script:

UnityEngine.Application.RegisterLogCallback(CaptureLog);
https://docs.unity3d.com/ScriptReference/Application.LogCallback.html

A very comfortable way of displaying your logs at runtime is KGFDebug.
Check it out.

Hi @NinjaSquirrel !

The easiest way is to use the Debug.LogAssertion.

Debug.LogAssertion("Message to show in Development Build/Console");

If you want you can also create a simple log file to save your debug using some WebService or even saving in your computer (if standalone builds).

You do something like:

private void MyDebug(string message){
        Debug.Log(message);
        Debug.LogAssertion (message); //you can see in game console

        WWWForm form = new WWWForm();
        form.AddField("newMessage", message);
        string url = "http://yourserver/saveUnityLog.php";
        WWW download = new WWW(url, form);
}

In the file saveUnityLog.php you just need to add a new line in some file like myLog.txt. :wink:

NOTE: If in standalone you can use the localhost for sure. Also is a good idea add a datetime for each message.

Good luck.

I have a solution in my new video :slight_smile:

If you have Android Studio installed, then you see all the logs in the Android Studio’s Logcat.

You can use GameLog.
Here’s the link: GitHub - Kiarash-Parvizi/GameLog: High-Performance Portable Log System for unity

Its free and easy to use

I know this is old thread but this is still a valid question now. I was looking for a quick answer without any extra code, this is the easiest way.

I found that console Debug.Log messages are by default written to a file.
If not, you can enable this in the Project Setting → Player → Standalone Player Options
For Uunity 2020.3:

Linux	~/.config/unity3d/CompanyName/ProductName/Player.log
macOS	~/Library/Logs/Company Name/Product Name/Player.log
Windows	%USERPROFILE%\AppData\LocalLow\CompanyName\ProductName\Player.log

See Unity - Manual: Log files for the latest locations, it seems that the location has been changed in different unity versions.

I hope that helps.,I know this is old thread but this is still a valid question now. I was looking for a quick answer without any extra code, this is the easiest way.

I found that console Debug.Log messages are by default written to a file.
If not, you can enable this in the Project Setting → Player → Standalone Player Options
For Uunity 2020.3:

Linux	~/.config/unity3d/CompanyName/ProductName/Player.log
macOS	~/Library/Logs/Company Name/Product Name/Player.log
Windows	%USERPROFILE%\AppData\LocalLow\CompanyName\ProductName\Player.log

See Unity - Manual: Log files for the latest locations, it seems that the location has been changed in different unity versions

I spent a couple of hours creating a logging system which:

  1. Works on all platforms
  2. Reasonably performant
  3. Has the option to silence duplicate log messages
  4. Does not cause memory overload
  5. Holds the most recent N logs in memory
  6. Collects all logs, even from different threads (using logMessageReceivedThreaded. See: Unity Document)
  7. Allows me to copy log chunks to the clipboard when clicking a custom button on the SRDebugger Options tab.

You can turn this into a Singleton if you want as well. If you do not have SRDebugger added into your project, simply delete lines that start with “SROptions”.

    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using UnityEngine;
    public class LogRecordService : MonoBehaviour //WARNING: Do not Debug.Log() inside this class, it might create an endless loop.
    {

    #region SingletonImplementation
    public static LogRecordService instance;

    void Awake()
    {
        if (instance != null)
        {
            Destroy(gameObject);
        }
        else
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
    }
    #endregion

        const int INITIAL_CHARACTER_CAPACITY = 15000;
        const int MAXIMUM_NUMBER_OF_RECORDED_LOGS = 300;

        private List<LogEntry> _logEntries;
        private StringBuilder _stringBuilder;
        
        public void Start() //WARNING: If you won't use Singleton, you better unsubscribe from those events, for instance within OnDestroy()
        {
            _logEntries = new List<LogEntry>();

            Application.logMessageReceivedThreaded += HandleLogMessageReceived;
            SROptions.OnCopyAllLogsButtonPressed += HandleCopyAllLogsButtonPressed;
            SROptions.OnCopyAllDistinctLogsButtonPressed += HandleCopyAllDistinctLogsButtonPressed;
        }

        private void HandleCopyAllLogsButtonPressed()
        {
            CopyLogEntryListToClipboard(_logEntries);
        }     
        
        private void HandleCopyAllDistinctLogsButtonPressed()
        {
            List<LogEntry> _logEntriesWithoutDuplicates = _logEntries.Distinct(new LogEntryComparer()).ToList();

            CopyLogEntryListToClipboard(_logEntriesWithoutDuplicates);
        }
        
        private void CopyLogEntryListToClipboard(List<LogEntry> logEntries)
        {
            _stringBuilder = new StringBuilder(INITIAL_CHARACTER_CAPACITY);

            foreach (LogEntry logEntry in logEntries)
            {
                _stringBuilder.Append(logEntry.LogString + "

" + logEntry.StackTrace + "
");
}

            GUIUtility.systemCopyBuffer = _stringBuilder.ToString();
        }     
            
        public void HandleLogMessageReceived(string logString, string stackTrace, LogType type)
        {
             //#if !UNITY_EDITOR //You can make the functions only work outside UNITY_EDITOR to get a small performance boost while working on other stuff if you want.

            LogEntry newLogEntry = new LogEntry(logString, stackTrace, type);
            _logEntries.Add(newLogEntry);

            if (_logEntries.Count > MAXIMUM_NUMBER_OF_RECORDED_LOGS)
            {
                _logEntries.RemoveAt(0);
            }

            //#endif

        }

    }

    internal class LogEntry
    {
        public string LogString { get; }
        public string StackTrace { get; }
        public LogType Type { get; }

        public LogEntry(string logString, string stackTrace, LogType type)
        {
            LogString = logString;
            StackTrace = stackTrace;
            Type = type;
        }
    }
    
    internal class LogEntryComparer : IEqualityComparer<LogEntry>
    {
        public int GetHashCode(LogEntry logEntry)
        {
            return 0;
        }
        
        public bool Equals(LogEntry x, LogEntry y)
        {
            return x != null 
                   && y != null                    
                   && x.LogString.Equals(y.LogString)
                   && x.StackTrace.Equals(y.StackTrace)
                   && x.Type.ToString().Equals(y.Type.ToString());
        }
    }

Here is the SRDebugger related code that I added (The name of the class is not SROptions but SROptions.Debug.cs in the file system, since it is a partial class.):

using System;
using System.ComponentModel;
using UnityEngine;
    
public partial class SROptions
{
    public static event Action OnCopyAllLogsButtonPressed;
    public static event Action OnCopyAllDistinctLogsButtonPressed;
    
    [Category("Utilities")]
    public void CopyAllLogs()
    {
        OnCopyAllLogsButtonPressed();
    }   
    
    [Category("Utilities")]
    public void CopyAllDistinctLogs()
    {
        OnCopyAllDistinctLogsButtonPressed();
    }
    
    [Category("Utilities")]
    public void ClearPlayerPrefs() {
        Debug.Log("Clearing PlayerPrefs"); 
        PlayerPrefs.DeleteAll();
    }
    
    [Category("Utilities")]
    public void CopyDeviceUniqueID() { 
        GUIUtility.systemCopyBuffer = SystemInfo.deviceUniqueIdentifier;
    }
}