-
Notifications
You must be signed in to change notification settings - Fork 3
Writing output to the console
When using the DeveloperConsole package, you will at some point want to write output to the console. The DeveloperConsole API provides support for basic log, warning, and error messages, as well as support for outputting custom images and media through the DeveloperConsole.AppendEntry
method, described below. In addition, any output from the Unity console will be logged to the in-game developer console by default, unless you tell it not to inside the console settings.
Three methods are provided to log text to the console:
public static void DeveloperConsole.Log(object message);
public static void DeveloperConsole.LogWarning(object message);
public static void DeveloperConsole.LogError(object message);
The string form (i.e. message.ToString()
) of the given message will be taken and logged to the console in a white color (Log
), amber color (LogWarning
), or red color (LogError
). These colors can be customized in the console settings. Additionally, variants of these functions are provided for formatted strings:
public static void DeveloperConsole.LogFormat(string format, params object[] args);
public static void DeveloperConsole.LogWarningFormat(string format, params object[] args);
public static void DeveloperConsole.LogErrorFormat(string format, params object[] args);
and can be used like so:
using Cronyx.Console;
DeveloperConsole.LogFormat("{0} {1}!", "Hello", "World");
// Prints "Hello World!" to the console.
Virtually any user-created output, such as an image, video, or color picker, can be logged to the console by creating a custom ConsoleEntry
class for that ouptut. ConsoleEntry
is an abstract MonoBehaviour
that defines an arbitrary entry to the console.
Creating your own ConsoleEntry
and logging it to the console is a three-step process:
- Create a class extending
ConsoleEntry
that optionally overrides one or more of the virtual methods described below. - Create a prefab whose root
GameObject
has yourConsoleEntry
component attached. - Pass this prefab to
DeveloperConsole.AppendEntry
to instantiate it and return an instance of yourConsoleEntry
component.
The rest of this article will demonstrate this procedure by creating a ConsoleEntry
that takes and logs a screenshot to the console.
In order to create a ConsoleEntry
that logs a screenshot to the console, we will override several of the virtual methods provided by ConsoleEntry
to take and display a screenshot. Refer to the following source code:
public class ScreenshotEntry : ConsoleEntry
{
[SerializeField]
private RawImage Image; // A raw image that will store the screenshot texture
[SerializeField]
private TextMeshProUGUI Caption; // A text component that will show a caption for the screenshot
private Texture2D mTexture; // A texture object to store the screenshot data (so we can delete it later)
// Use the Configure method to update this component so that it conforms to the console's visual settings,
// such as the font, font color, or font size
public override void Configure(ViewSettings settings)
{
Caption.font = settings.Font;
Caption.fontSize = settings.FontSize;
Caption.color = settings.FontColor;
// Make caption's height equal to the font height
Caption.rectTransform.sizeDelta = new Vector2(Caption.rectTransform.sizeDelta.x, settings.FontSize);
}
// Use the OnCreated method to handle any initialization code.
// This method is guaranteed to be called after Configure.
public override void OnCreated()
{
}
// OnRemoved is called just before this component is destroyed.
// Use it to perform any cleanup, release any resources, etc.
public override void OnRemoved()
{
// Destroy the texture object to free up memory
if (mTexture != null) Destroy(mTexture);
}
public void SetData (Texture2D texture, string caption)
{
mTexture = texture;
Image.texture = mTexture;
Caption.text = caption;
}
}
Notice that in the Configure
method, we use the passed ViewSettings
object to adjust our console entries appearance so that it conforms to that of the console. ViewSettings
contains data about the default console font, font size, font color, etc. OnCreated
can be used for any initialization code, and similarly, OnRemoved
can be used for any destruction code.
We do not take the screenshot directly inside this ConsoleEntry
(for instance, inside its OnCreated
method) as this would cause the console entry itself to appear in the screenshot. Rather, we let the creator of this console entry set the screenshot manually using the SetData
method.
Next, we must create a prefab that will house the above ScreenshotEntry
component. There are a few stipulations/recommendations concerning the prefab that is used for console entries:
- The prefab's root
GameObject
must have yourConsoleEntry
implementation attached as a component. - The prefab's root
GameObject
must have aRectTransform
(so that it can be used inside the UI). - The prefab's root
GameObject
should have aContentSizeFitter
component attached so that your entry only uses as much space as it needs. - The prefab's root
RectTransform
should have an x-pivot equal to zero (so that it is left-justified inside the console).
For our ScreenshotEntry
component, we will use the following hierarchy. ScreenshotEntry
is the root GameObject
for our console entry, RawImage
will hold our screenshot image, and finally Caption
will hold a TextMeshPro text component that displays a caption beneath the image.
Let's start designing the Prefab:
In the editor, the finished prefab looks like this:
The white rectangle represents where the screenshot will appear, and the text beneath it holds the caption.
Finally, we will save the prefab to our resources folder so we can easily access it at runtime in our code:
To create and use your console entry, call the following function:
public static T DeveloperConsole.AppendEntry<T>(GameObject prefab) where T : ConsoleEntry;
The AppendEntry
function will instantiate your prefab, add it to the UI, and return an instance of your ConsoleEntry
implementation, T
.
In the case of our screenshot entry, we will write a console command using the IConsoleCommand
pattern (see here for more information) that waits until the end of the frame to fetch a screenshot and displays it:
[Command("screenshot")]
public class ScreenshotCommand : MonoBehaviour, IConsoleCommand
{
public string Help => "Takes and displays a screenshot";
private Coroutine mCoroutine;
public void Invoke(string data)
{
if (mCoroutine != null) StopCoroutine(mCoroutine);
mCoroutine = StartCoroutine(ShowScreenshot());
}
// A coroutine that will take and show the screenshot
private IEnumerator ShowScreenshot()
{
yield return new WaitForEndOfFrame();
// Take a screenshot (in the form of a Texture2D)
Texture2D texture = new Texture2D(Screen.width, Screen.height, TextureFormat.RGB24, false);
texture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0);
texture.Apply();
// Get a caption for the image containing the date
var now = DateTime.Now;
string caption = $"Taken on {now.ToString("dddd, dd MMMM yyyy")} at {now.ToString("HH:mm:ss")}";
// Create ScreenShot entry
var entry = DeveloperConsole.AppendEntry<ScreenshotEntry>(Resources.Load<GameObject>("ScreenshotEntry"));
entry.SetData(texture, caption);
}
}
Notice how we created an entry using DeveloperConsole.AppendEntry
, and passed a prefab loaded from resources using Resources.Load
.
We are now able to call the screenshot
command to take and display a screenshot, like so:
A similar process can be followed to add any other custom content to the console.