# Hiro Store Sample Project

**URL:** https://heroiclabs.com/docs/sample-projects/unity/hiro-store/
**Summary:** Player Store system sample project for Unity games
**Keywords:** hiro store, nakama client, hiro store coordinator, unity sdk, systems-based architecture, authentication, sample project, deterministic startup, system lifecycle, network monitor
**Categories:** unity, sample-projects, hiro-store

---


## Code overview

The project uses Hiro’s systems-based architecture, which provides an opinionated structure for building games with pre-configured systems.

### Coordinator (`HiroStoreCoordinator.cs`)

Extends the HiroCoordinator class to set up the Nakama connection and initialize Hiro systems. It handles system lifecycle and authentication before your game logic runs. For details, see [Hiro's deterministic startup](../../../hiro/unity/getting-started/nakama-system/#hiro-deterministic-startup).

```csharp
protected override Task<Systems> CreateSystemsAsync() {
    var logger = new Hiro.Unity.Logger();
    var monitor = NetworkMonitor.Default;
    var client = localHost
        ? new Client("http", "127.0.0.1", 7350, "defaultkey")
        : new Client(scheme, host, port, serverKey);
    var nakamaSystem = new NakamaSystem(logger, client, NakamaAuthorizerFunc());

    var storage = MemoryStorage.Default;

    // Register necessary Hiro Systems
    var systems = new Systems(nameof(HiroStoreCoordinator), monitor, storage, logger);
    systems.Add(nakamaSystem);
    var economySystem = new EconomySystem(logger, nakamaSystem, EconomyStoreType.Unspecified);
    systems.Add(economySystem);

    return Task.FromResult(systems);
}
```

API reference: [Hiro Initialization](../../../hiro/unity/getting-started/nakama-system)

---

### Controller (`StoreController.cs`)

Coordinates between the store UI and the Hiro Economy. Subscribes to init and view events, maintains the catalog, wallet, and item cache, and executes purchases through EconomySystem with affordability checks and state refresh.

#### Store operations

**Refresh store**

Pull latest store data, cache items, and refresh the UI.


```csharp
public async Task RefreshStore()
{
    try
    {
        await _economySystem.RefreshStoreAsync();
        await _economySystem.RefreshAsync();

        StoreItems.Clear();
        StoreItems.AddRange(_economySystem.StoreItems);

        Debug.Log($"Loaded {StoreItems.Count} store items");

        // Find featured item for Featured tab
        _featuredItem = (EconomyListStoreItem)StoreItems.FirstOrDefault(item => 
            item.Category == "featured" || item.Name.ToLower().Contains("starter"));

        // Find lootbox item for Deals tab
        _lootboxItem = (EconomyListStoreItem)StoreItems.FirstOrDefault(item => 
            item.Category == "lootbox" || item.Name.ToLower().Contains("lootbox") || 
            item.Name.ToLower().Contains("mystery"));

        await _view.RefreshStoreDisplay();
    }
    catch (Exception e)
    {
        Debug.LogException(e);
        _view.ShowError($"Failed to refresh store: {e.Message}");
    }
}
```
#### Purchase operations

**Purchase item**

Attempt a purchase by item ID, refresh economy data on success, and bubble up errors.

```csharp
public async Task<IEconomyPurchaseAck> PurchaseItem(IEconomyListStoreItem item)
{
    if (item == null)
        throw new Exception("No item selected");

    try
    {
        IEconomyPurchaseAck result;
        result = await _economySystem.PurchaseStoreItemAsync(item.Id);
        Debug.Log($"Purchased {item.Name} successfully");

        // Refresh economy
        await _economySystem.RefreshAsync();

        return result;
    }
    catch (Exception e)
    {
        Debug.LogError($"Purchase failed: {e.Message}");
        throw;
    }
}
```

#### Additional operations

**Can afford item**

Check wallet balances against all currency costs for an item.

API reference: [Store](../../../hiro/unity/economy/virtual-store/)

---

### Views

**StoreView** 

Main store screen wiring tabs, wallet, featured item, grid population, and purchase/reward/error modals.

**StoreItemView**

Single store item tile showing icon, amount/name, badges, price/currency, and purchase button behavior.

**CodexItemView**

Codex entry display for inventory items with name, description fallback, category, and consumable flag.
