Redirect Console.Write to Unity’s Console
One of the great advantages of programming in Unity is that it uses a (mostly) standard .NET implementation. This means you can find lots of third party code that is written for .NET but not necessarily Unity and still incorporate it into your app. This kind of code typically uses System.Console.Write
or System.Console.WriteLine
to print to standard output, but Unity doesn’t display it in its Console panel or redirect it to platform-specific logging like Android’s logcat
. This article provides a class you can easily integrate into your app to redirect System.Console
writes to Unity’s standard Debug
logging so it’ll show up like you’d expect.
The key to redirecting System.Console
writes is to use the System.Console.SetOut
function. It takes a System.IO.TextWriter
which has many Write
and WriteLine
functions for all kinds of types: int
, string
, double
, etc.
Defining this TextWriter
is most of the work. Thankfully, most of them redirect to just three Write
functions:
public override void Write(string value) public override void Write(char value) public override void Write(char[] value, int index, int count)
Since writes might not be the entire line, a buffer must be kept to accumulate writes until a newline is written. System.Text.StringBuilder
is great for that.
Here’s the final source for the UnitySystemConsoleRedirector
:
using System; using System.IO; using System.Text; using UnityEngine; /// <summary> /// Redirects writes to System.Console to Unity3D's Debug.Log. /// </summary> /// <author> /// Jackson Dunstan, http://jacksondunstan.com/articles/2986 /// </author> public static class UnitySystemConsoleRedirector { private class UnityTextWriter : TextWriter { private StringBuilder buffer = new StringBuilder(); public override void Flush() { Debug.Log(buffer.ToString()); buffer.Length = 0; } public override void Write(string value) { buffer.Append(value); if (value != null) { var len = value.Length; if (len > 0) { var lastChar = value [len - 1]; if (lastChar == '\n') { Flush(); } } } } public override void Write(char value) { buffer.Append(value); if (value == '\n') { Flush(); } } public override void Write(char[] value, int index, int count) { Write(new string (value, index, count)); } public override Encoding Encoding { get { return Encoding.Default; } } } public static void Redirect() { Console.SetOut(new UnityTextWriter()); } }
Using it is trivial:
UnitySystemConsoleRedirector.Redirect();
Then use Console
like normal in either your own code or the third party’s code, such as a DLL.
Here’s some code to test it out along with the output you’ll see in the Console panel of the Unity Editor:
UnitySystemConsoleRedirector.Redirect(); Console.WriteLine("str"); // output: str Console.WriteLine('A'); // output: A Console.Write('B'); Console.Write('C'); Console.Write('D'); Console.Write('\n'); // output: BCD Console.Write(123); Console.Write('\n'); // output: 123 Console.Write(3.14f); Console.Write('\n'); // output: 3.14 Console.Write(2.2); Console.Write('\n'); // output: 2.2 Console.Write(42.42m); Console.Write('\n'); // output: 42.42 Console.Write(new char[]{'H','I','J'}); Console.Write('\n'); // output: HIJ Console.Write(true); Console.Write('\n'); // output: True Console.Write(new object()); Console.Write('\n'); // output: System.Object Console.Write("some int: {0}", 123); Console.Write('\n'); // output: some int: 123 Console.Write(new char[]{'H','E','L','L','O'}, 1, 2); Console.Write('\n'); // output: EL
It’s really quite easy to integrate and minimal extra code in the project, so you might as well drop this in any time some third-party code is using System.Console
. You can also easily customize it if you’d rather redirect to a different logging system, file, or even network. Just replace the one Debug.Log
line with your own logging function.
Got any other logging tips for Unity? Ways to make working with third party code easier? If you do, go ahead and post a comment!
#1 by LIB53 on August 13th, 2015 ·
Wow, thanks for the write up. I’ve been experimenting with moving source code out of the Unity environment. Not being able to print to Unity’s console was a flaw. This is a rather neat solution! I’m actually trying to see what happens if I target .NET core and build DLLs from the newer compilers for my source code. From the little I’ve had time to mess with so far, I know that If you’re trying to create some engine agnostic code, you can use System.Numerics for Vector3, Matrix4x4, and Quaternion.
#2 by Patrick N. on January 7th, 2016 ·
Thank you. This was very helpful.
I am working on a multiplayer game with a standalone .net server and shared class libraries so this was just what I needed.
#3 by Matthew on February 8th, 2016 ·
Thank you for this. I just integrated into my Unity utilities and it worked perfectly.
#4 by Charles on June 1st, 2016 ·
Thanks so much for taking the time to create this class! I was working on a class that I wanted to make compatible with the traditional Microsoft Dev tools but also have it work in Unity3D. This worked perfectly.
Thanks again for your hard work!
#5 by Ra on December 30th, 2018 ·
Thank you for this! It works like a miracle :)
#6 by Benjamin Guihaire on May 27th, 2019 ·
this implementation is not thread safe ! StringBuilder buffer can be accessed from multiple threads.
#7 by Bejamin Guihaire on May 27th, 2019 ·
here one possibility,
-thread safe,
-does add the ‘\n’ to the stream if not needed,
-doesn’t convert to char -> string -> string builder when we can go directly to string builder
– and automatically starts the redirect:
public class ConsoleRedirect : TextWriter
{
private StringBuilder buffer = new StringBuilder();
public override void Flush()
{
string str;
lock(this)
{
str = buffer.ToString();
buffer.Length = 0;
}
UnityEngine.Debug.Log(str);
}
private void FlushNoLock()
{
string str = buffer.ToString();
buffer.Length = 0;
UnityEngine.Debug.Log(str);
}
public override void Write(string value)
{
if (value != null)
{
var len = value.Length;
if (len > 0)
{
lock(this)
{
var lastChar = value [len – 1];
if (lastChar == ‘\n’)
{
if(len>1)
buffer.Append(value,0,len-1);
FlushNoLock();
}
else
{
buffer.Append(value,0,len);
}
}
}
}
}
public override void Write(char value)
{
lock(this)
{
if (value == ‘\n’)
{
FlushNoLock();
}
else
{
buffer.Append(value);
}
}
}
public override void Write(char[] value, int index, int count)
{
if(count>0)
{
lock(this)
{
var lastChar = value [index + count – 1];
if (lastChar == ‘\n’)
{
if(count>1)
buffer.Append(value,index,count-1);
FlushNoLock();
}
else
{
buffer.Append(value,index,count);
}
}
}
}
public override Encoding Encoding
{
get { return Encoding.Default; }
}
[RuntimeInitializeOnLoadMethod]
private static void Redirect()
{
System.Console.SetOut(new ConsoleRedirect());
}
}
#8 by Maarten Schadd on March 27th, 2020 ·
Thanks! Works perfect. Now I can see the console output that my dll’s are generating. I do not want to let those libraries depend on unity.
#9 by Anton Sluijtman on October 20th, 2020 ·
Thanks a lot!
Now I can integrate my DDL’s used by console applications with Unity.
Years after publishing this, it still makes people (me!) happy!
Cheers!
#10 by James on November 12th, 2020 ·
Thank you very much!
Works perfectly!
Best Wishes,
James!
#11 by Ang M on March 21st, 2021 ·
This is beautiful and powerful.
Thanks!
#12 by Seromu on April 12th, 2023 ·
Since updating to Unity 2022.2, I have experienced an issue where the Progress Bar displaying ‘ScriptCompilation: Running Backend’ during script compilation never completes.
To reproduce the issue: In the Unity Editor, press Play -> Execute ‘UnitySystemConsoleRedirector.Redirect()’ on some Monobehaviour -> Stop -> Edit your script -> Return to Unity -> ‘ScriptCompilation: Running Backend’ never finishes.
If you are experiencing a similar issue, it is recommended to avoid using this plugin or modify it for your use.
#13 by Seromu on April 12th, 2023 ·
Here is my solution.
If you using Unity 2022.2 above, you must call this before script compilation.
#14 by Seromu on April 12th, 2023 ·
Here is my solution.
If you using Unity 2022.2 above, you must call ‘Restore’ before script compilation.
public static void Redirect()
{
if (_defaultTextWrite == null)
{
_defaultTextWrite = Console.Out;
Console.SetOut(new UnityTextWriter());
}
}
///
/// If you using Unity 2022.2 above, you must call this before script compilation
/// Otherwise, you may encounter an issue where script compilation never finishes.
///
public static void Restore()
{
if (_defaultTextWrite != null)
{
Console.SetOut(_defaultTextWrite);
}
}