__Have you ever needed to sort your inventory items by rarity, or rank your enemies based on distance to the player? Writing custom sorting logic in Unity can quickly become messy if you don’t know about two powerful C# interfaces: IComparable and IComparer. In this post, we'll look at how you can use these interfaces to cleanly organize and sort your data in Unity — with real-world examples like an inventory system.Since the today's discussion is all about Sorting things , our inventory system will be pretty small , but you can scale it however you want (i also suggest to using Scriptable Objects).
What is IComparable interface?
The IComparable interface in C# is used to define a natural (default) sorting order for objects of a class.
You implement this interface when your objects should be able to compare themselves to other objects of the same type.
This allows you to use methods like List.Sort() directly without needing an external comparer.
Use this interface to implement a default comparison.
What is IComparer interface?
The IComparer interface is used to define custom or external sorting logic for objects.
You use this interface when you want to define multiple ways to compare objects, or when you can't modify the original class.
You pass the comparer as an argument to sorting methods like List.Sort(IComparer).
Item class
Item class is pretty simple , it holds the item data , implements IComparable interface for default comparison
public class Item : IComparable<Item>
{
public int Id { get; }
public int Power { get; }
public Rarity Rarity { get; }
public Item(int id, int power, Rarity rarity)
{
Id = id;
Power = power;
Rarity = rarity;
}
// Comes from IComparable interface , it helps to define 'default' sorting logic.
public int CompareTo(Item other)
{
// let's compare ids as default
return this.Id.CompareTo(other.Id);
}
}
public enum Rarity
{
Common,
Rare,
Legendary
}
Comparer classes
Comparer classes implement IComparer interface, which allows us to define custom comparing logic.Since we implemented default comparison logic by using IComparable interface in Item class, let's create our own Comparer classes.I will start with Power comparer:
/// <summary>
/// Use this class to sort items based on their power
/// </summary>
public class ItemPowerComparer : IComparer<Item>
{
// Compares by power
public int Compare(Item x, Item y)
{
return x.Power.CompareTo(y.Power);
}
}
And now — let’s sort our items based on Rarity.
💡 Remember: enums in C# are backed by integers by default. So comparing enum values is just like comparing integers — and the C# compiler is smart enough to handle that elegantly under the hood.
/// <summary>
/// Use this class to sort items based on their rarity
/// </summary>
public class ItemRarityComparer : IComparer<Item>
{
// Compares by Rarity
public int Compare(Item x, Item y)
{
return x.Rarity.CompareTo(y.Rarity);
}
}
Inventory class
I think we all get it.Let's use it in action.It's time for our big guy Inventory class.I will make it simple for the sake of this tutorial but you can extend it however you want.
public class Inventory : MonoBehaviour
{
// Item list
private readonly List<Item> items = new List<Item>()
{
new Item(id: 0 , power:10 , rarity:Rarity.Rare),
new Item(id: 1 , power:6 , rarity:Rarity.Common),
new Item(id: 2 , power:7 , rarity:Rarity.Legendary)
};
private void Update()
{
// default sorting
if (Input.GetKeyDown(KeyCode.Space))
{
Sort();
// output : 0,1,2 -> when sorted by id
}
//Power sorting
if (Input.GetKeyDown(KeyCode.P))
{
Sort(new ItemPowerComparer());
// output : 1,2,0 -> when sorted by power
}
//Rarity sorting
if (Input.GetKeyDown(KeyCode.R))
{
Sort(new ItemRarityComparer());
// output : 1,0,2 -> when sorted by Rarity
}
}
public void Sort(IComparer<Item> comparer = null)
{
items.Sort(comparer); // sorts by ascending
foreach (Item item in items)
{
Debug.Log($"\n {item.Id}");
}
}
}
Conclusion
Sorting is one of those things that sounds simple — until your game needs to rank, order, or organize complex data. Thankfully, with IComparable and IComparer, you can keep your logic clean, modular, and easy to extend.
Whether you're building a full inventory system, a quest tracker, or a leaderboard, these interfaces will save you from messy code and hard-to-maintain conditionals_
Thanks for reading
buy me a coffee
Top comments (0)