Documentation

Unity Engine


User Manual

Script Reference

Unity Engine


Create a custom formatter

Write your own formatter to convert a value into text inside a Smart String.
Read time 4 minutesLast updated 6 days ago

Write your own formatter to convert a value into text inside a Smart String.
To write your own custom formatter, create a class that inherits from the
FormatterBase
class (namespace
Unity.SmartStrings.Core.Extensions
). Override the
DefaultName
property to set the name used to apply it. Override the
TryEvaluateFormat(IFormattingInfo)
method to implement your custom formatting. Register the formatter with
Smart.Default.AddExtensions(...)
so Smart Strings can use it.

Write the formatter

Inherit from the
FormatterBase
class (namespace
Unity.SmartStrings.Core.Extensions
) in your custom formatter. Override the
TryEvaluateFormat
method and inspect
IFormattingInfo.CurrentValue
to check whether the formatter can handle the value. If it can, write the output with
IFormattingInfo.Write(...)
and return
true
. If it can't, return
false
so the next formatter is tried.
The
CanAutoDetect
property is
false
by default, so your custom formatter only runs when applied by name. You can override this property and set it to
true
to run the formatter implicitly even when no name is given. If this is enabled, return
false
for values you can't handle in the
TryEvaluateFormat
method, so subsequent formatters get a chance to resolve the formatting.
If your custom formatter needs to be set up before it can be used properly (for example, if it needs to read the case-sensitivity setting), you can implement
IInitializer
and its
Initialize(SmartFormatter)
. This method runs when the formatter is registered, and again after the settings asset deserializes.
The following Byte formatter example converts a byte count into a human-readable size. It handles a
long
value and returns
false
for anything else, so it only applies when the value is a
long
.
public class ByteFormatter : FormatterBase { public override string DefaultName => "byte"; public override bool TryEvaluateFormat(IFormattingInfo formattingInfo) { if (formattingInfo.CurrentValue is long bytes) { // We are performing a Base 2 conversion here. 1024 bytes = 1 KB if (bytes < 512) { formattingInfo.Write($"{bytes} B"); return true; } if (bytes < 512 * 1024) { var kb = bytes / 1024.0f; formattingInfo.Write($"{kb.ToString("0.00")} KB"); return true; } bytes /= 1024; if (bytes < 512 * 1024) { var mb = bytes / 1024.0f; formattingInfo.Write($"{mb.ToString("0.00")} MB"); return true; } bytes /= 1024; var gb = bytes / 1024.0f; formattingInfo.Write($"{gb.ToString("0.00")} GB"); return true; } return false; } }

Register the formatter

To enable your formatter, register it using the
Smart.Default.AddExtensions(...)
method. Then apply it by name:
Smart.Default.AddExtensions(new ByteFormatter()); Smart.Format("The file size is {0:byte}", 1234L); // "The file size is 1.21 KB"

Smart String

Argument

Result

The file size is {0:byte}
100
The file size is 100 B
The file size is {0:byte}
1000
The file size is 0.98 KB
The file size is {0:byte}
1234
The file size is 1.21 KB
The file size is {0:byte}
10000000
The file size is 9.54 MB
The file size is {0:byte}
2000000000
The file size is 1.86 GB
You can also add a custom formatter to the project's default formatter without code: in the Smart Strings settings, select Add (+) on the Formatters list and choose your formatter from the menu, which lists every available formatter type by name. Mark the class
[Serializable]
and give it a public parameterless constructor so it can be added and saved with the settings.

Extract literal text

If your formatter chooses between literal text branches, like the Choose, Conditional, and Null formatters do, implement
IFormatterLiteralExtractor
and its
WriteAllLiterals(IFormattingInfo)
method. In it, write every literal the formatter could output, not only the branch that matches the current value. Tools that walk a Smart String's literal text use this to find text that appears in only some branches.
For example, a tool can call
WriteAllLiterals
across every Smart String in a project to collect all the unique characters those strings could produce, then generate a font atlas that contains exactly those glyphs. Without it, a branch that isn't taken when the text is scanned would be missing from the extracted characters, so its glyphs could be absent from the atlas and fail to render at runtime.

Additional resources