A dynamic, runtime string interpolation tool for Unity, supporting custom formatting and expressions.
- Dynamic string interpolation at runtime.
- Support for custom formats via
IRichStringCustomFormat
. - Rich text parsing and rendering.
- Property referencing for objects and collections (
IEnumerable
). - Easily extensible and configurable error handling modes.
Welcome to RichString, a powerful runtime string interpolation solution designed specifically for Unity. This guide will walk you through the installation process and help you get started using RichString in your project.
Download the latest release from the GitHub releases page. Simply extract the files and place the RichString folder anywhere in your Unity project’s Assets
directory. Done!
The following example demonstrates how RichString can be used to interpolate strings at runtime.
A simple example is provided where a Weapon
class and an Inventory
class are defined. RichString
will be used to dynamically reference properties from these classes in runtime string expressions.
A basic Weapon
class with properties such as Damage
and FireRate
is defined:
public class Weapon
{
[field: SerializeField] public int damage { get; private set; }
[field: SerializeField] public int fireRate { get; private set; }
}
Here’s a basic Inventory
class containing RichString
and MaxSlots
fields, along with a Weapon
instance and a list of Weapon
. The RichString
object must be initialized with the object whose properties are going to be referenced (in this case, this). Initialization must be performed in the Start()
or Awake()
method (in a MonoBehaviour
) or anywhere before invoking GetParsedString()
.
To get the final parsed string, GetParsedString()
should be called.
public class Inventory : MonoBehavior
{
[SerializeField] RichString _description;
[field: SerializeField] public int MaxSlots { get; set; }
[field: SerializeField] public List<Weapon> weapons { get; private set; } = new();
[field: SerializeField] public Weapon mainWeapon { get; private set; }
public void Start()
{
_description.Initialize(this);
}
public string GetDescription()
{
return _description.GetParsedString();
}
}
Texts and expressions can be written using RichString
by following the rules in the next section Expressions.
Rules for Writing Expressions with RichString
This section outlines the rules for crafting expressions using the powerful RichString system, which allows for seamless property referencing and rich text formatting. By following these guidelines, you can create dynamic strings that enhance the interactivity and visual appeal of your content.
While the specifiers shown here are the defaults, they can be customized to fit your needs via RichStringSettings
in the asset folder.
-
Property Reference
A property can be referenced by placing the property name within curly braces
{}
.Your Inventory has {MaxSlots} slots.
-
Property in an Instance
To reference a property of a nested object, a dot
.
should be used to access the property, similar to regular code.Your Main Weapon deals {mainWeapon.damage} damage.
It can be chained as many times as desired:
{Instance1.Instance2.Instance3.Instance4.Instance5}
-
Element of an
IEnumerable
An element from an
IEnumerable
can be accessed by using the arrow->
to separate the property name from the desired index.These references can also be nested to access properties of objects contained within collections.
Your First Weapon deals {weapons->0.damage}
-
Formatting
To apply formatting to the text, double colon
::
should be placed between the text and the formatting specifier within square brackets[]
. The default formatting specifiers are as follows:Bold:
b
Italic:
i
Strikethrough:
s
Underline:
u
I am [Bold::b].
These formatting specifiers also can be nested to create combinations:
I am [Bold and Italic!::b::i].
A property can also be referenced as the text:
Your Main Weapon deals [{mainWeapon.damage}::b::u] damage.
-
Colorizing
To colorize a part of the text, first, the
Color Key
s must be declared in theRichStringSettings
in the asset folder.To apply a color, the color key should be placed as a formatting specifier within square brackets [], similar to how bold or italic formatting is applied.
I am [Green::green]! I am [Green and Bold::green::b]!
Using default Unity colors (like green, red etc.) is not supported in this version. For using them, they must be declared in
RichStringSettings
.
As with all other features in RichString, these formatting options can be seamlessly nested, allowing for powerful and flexible text manipulation.
Your Main Weapon deals [{mainWeapon.damage}::b::u::red] damage.
These are all the rules to be followed in the current version, but more will be added in future updates.
Until now, referencing a property would replace it with its value. Types such as int
or string
have string=friendy values. But what if we want to reference a custom type? In this case, the IRichStringCustomFormat
interface can be utilized.
public interface IRichStringCustomFormat
{
public string GetNormalForm();
public string GetAlternateForm();
}
The GetParsedString()
method has a boolean parameter called alternate
, which defaults to false
. If this parameter is set to true
, references will be replaced with GetAlternateForm()
. If it is set to false
, they will be replaced with GetNormalForm()
, provided that IRichStringCustomFormat
has been implemented.
One example of an Alternate Form use case is when a player is required to hold a certain key to receive additional information in the description, prompting the same properties to change to a more informative and expanded form.
public class Weapon : IRichStringCustomFormat
{
[field: SerializeField] public int damage { get; private set; }
[field: SerializeField] public int fireRate { get; private set; }
public string GetNormalForm()
{
return $"Damage: {damage}";
}
public string GetAlternateForm()
{
return $"Damage: {damage}, Fire Rate: {fireRate}";
}
}
- Example:
Main Weapon
{mainWeapon}
The RichStringExtensions
class provides a set of extension methods that can be utilized in code to apply rich text formatting easily. These methods enable developers to enhance the presentation of strings by incorporating various styles directly within their code.
string text = "Some text";
text = text.Bold().Colorize(Color.green);
It may be beneficial for developers to leverage these extensions when implementing custom formatting in the
IRichStringCustomFormat
interface.
When referencing a property, the property name used in code should be utilized (rather than Unity's display name in the inspector), and RichReference
attribute facilitates easier access to it.
The RichReference
attribute contains two properties: showCopyButton
and richReferenceDraw
. When showCopyButton
is enabled, a copy button is drawn that will copy the main property's path to the clipboard.
The richReferenceDraw
property, which defaults to RichReferenceDrawType.DontDraw
, is an enum of type RichReferenceDrawType
, which includes the following options:
- DontDraw: No elements are drawn.
- Replace: The Unity display name is replaced with the main property name.
- Append: The main property name is drawn in front of the Unity display name.
public class Inventory : MonoBehavior
{
[SerializeField] RichString _description;
[field: SerializeField] public int MaxSlots { get; set; }
[field: SerializeField] public List<Weapon> weapons { get; private set; } = new();
[field: SerializeField]
[RichReference(richReferenceDraw = RichReferenceDrawType.Append)]
public Weapon mainWeapon { get; private set; }
public void Start()
{
_description.Initialize(this);
}
public string GetDescription()
{
return _description.GetParsedString();
}
}
ublic class Weapon : IRichStringCustomFormat
{
[field: SerializeField, RichReference] public int damage { get; private set; }
[field: SerializeField] public int fireRate { get; private set; }
public string GetNormalForm()
{
return $"Damage: {damage}";
}
public string GetAlternateForm()
{
return $"Damage: {damage}, Fire Rate: {fireRate}";
}
}
For example, here the copy button on the Main Weapon property will copy {mainWeapon}
and the one on the damage property will copy {mainWeapon.damage}
.
For the IEnumerable
types, the copy button on the Element 0 will copy {weapons->0}
and the one on the damage property of the Element 0 will copy {weapons->0.damage}
.
They can be pasted right away in the RichString
's expression.
In the event of an error, you can specify whether it should be handled as a warning or an error in RichStringSettings
. Handling it as an error may cause other parts of your code to stop functioning properly, so choose based on the severity of the issue. By default, errors are handled as warnings.
This is my very first tool asset for Unity, and I am excited to share it with you! There may be some issues, and I appreciate your understanding as I work on improvements. Your feedback is invaluable to me, so please don’t hesitate to report any issues you encounter in the Issues section