| Keywords | string, $"...", @"...", StringBuilder |
|---|---|
| Namespace | System, System.Text |
| In Unity | UI text, Debug.Log, save keys, dialogue |
Strings & Formatting
A string is text. This page covers building strings for UI and logs (interpolation and number formatting), common string methods, and how to avoid the performance trap of rebuilding text every frame.
String interpolation
Put $ before the quotes and write values inside { }. It's the clearest way to build text.
int coins = 42;
float time = 83.456f;
string a = "Coins: " + coins + " Time: " + time; // old way: concatenation
string b = $"Coins: {coins} Time: {time}"; // interpolation: same result, easier to read
Debug.Log($"{name} is at {transform.position}");
Formatting numbers
Add :format after the value inside the braces:
| Code | Result for 1234.5678 | Use for |
|---|---|---|
$"{x:F0}" | 1235 | Whole numbers (rounded) |
$"{x:F2}" | 1234.57 | 2 decimal places |
$"{x:N0}" | 1,235 | Thousands separators (scores) |
$"{x:0000}" | 1235 | Pad with zeros: 7 → 0007 |
$"{0.75f:P0}" | 75% | Percentages |
$"{x,8}" | " 1234.5678" | Right-align in 8 characters |
Separators and decimal points follow the player's system language (e.g. "1.234,57" in German) unless you pass CultureInfo.InvariantCulture.
A timer display
float seconds = 83.456f;
int m = (int)(seconds / 60f);
float s = seconds % 60f;
timerText.text = $"{m:00}:{s:00.00}"; // "01:23.46"
// Or with TimeSpan
var t = System.TimeSpan.FromSeconds(seconds);
timerText.text = t.ToString(@"mm\:ss"); // "01:23"
Useful string methods
| Method | Example | Result |
|---|---|---|
Length | "Hello".Length | 5 |
ToUpper() / ToLower() | "Hi".ToUpper() | "HI" |
Contains(s) | "Goblin King".Contains("King") | true |
StartsWith / EndsWith | name.StartsWith("Enemy_") | true/false |
Replace(a, b) | "(Clone)".Replace("(Clone)", "") | "" |
Split(c) | "a,b,c".Split(',') | ["a","b","c"] |
Trim() | " hi ".Trim() | "hi" |
Substring(start, len) | "Unity".Substring(0, 3) | "Uni" |
string.IsNullOrEmpty(s) | string.IsNullOrEmpty(input) | true if null or "" |
string.Join(sep, items) | string.Join(", ", names) | "Ana, Ben" |
string.Equals(a, b, StringComparison.OrdinalIgnoreCase) | compare ignoring case | true/false |
Special characters
string line = "First line\nSecond line"; // \n = new line
string quote = "She said \"hi\""; // \" = a quote inside the string
string path = @"C:\Games\Save"; // @ = backslashes are literal (verbatim)
string brace = $"Use {{braces}} like this"; // {{ }} = literal braces in interpolation
StringBuilder: building big strings
Strings can't be changed. Every + makes a new string and throws the old one away. For building long text in a loop, use StringBuilder, which grows one buffer instead.
Writing a letter in pen. With plain strings, fixing one word means rewriting the whole letter on a fresh sheet and throwing the old one away. A StringBuilder is a notepad in pencil: you keep adding and editing the same page, and only copy it out neatly (ToString()) at the end.
using System.Text;
private readonly StringBuilder sb = new StringBuilder(256); // reuse this one
void ShowInventory(List<Item> items)
{
sb.Clear();
sb.AppendLine("Inventory:");
foreach (Item item in items)
{
sb.Append("- ").Append(item.displayName).Append(" x").Append(item.count).AppendLine();
}
inventoryText.text = sb.ToString();
}
What happens at runtime
- Each new string is a heap allocation.
$"Score: {score}"inUpdatecreates garbage every frame, even if the score didn't change. - Setting a TextMeshPro
textproperty also makes it rebuild its mesh, which costs time. - So: only update text when the value actually changes.
private int shownScore = -1;
void Update()
{
if (score == shownScore) return; // nothing changed: no new string, no mesh rebuild
shownScore = score;
scoreText.text = $"Score: {score:N0}";
}
// Even better: update from a "score changed" event instead of polling in Update.
Common Mistakes
- Comparing with
==for user input when case doesn't matter. Usestring.Equals(a, b, StringComparison.OrdinalIgnoreCase). float.Parse("3.5")failing on some computers. In languages that use a comma for decimals, it throws or gives the wrong number. Usefloat.Parse(s, CultureInfo.InvariantCulture)for data you save and load.- Rebuilding UI text every frame. See above.
See also
- Optimizing Your Code
- Exceptions & try/catch (
TryParse)
This page is a simplified, AI-assisted interpretation. For the complete and authoritative reference, see the official Microsoft C# documentation.