# Hiro Challenges Sample Project

**URL:** https://heroiclabs.com/docs/sample-projects/unity/hiro-challenges/
**Summary:** Challenge and competition system sample project for Unity games
**Keywords:** hiro challenges, nakama integration, hiro coordinator, nakama system, unity sdk, authentication, systems architecture, competition system
**Categories:** unity, sample-projects, hiro-challenges

---


## Code overview

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

### Coordinator (`HiroChallengesCoordinator.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. Learn more about [Hiro's deterministic startup](../../../hiro/unity/getting-started/nakama-system/#hiro-deterministic-startup).

```csharp
// Create and register Hiro systems
protected override Task<Systems> CreateSystemsAsync() {
    var client = new Client(scheme, host, port, serverKey);
    var nakamaSystem = new NakamaSystem(logger, client, NakamaAuthorizerFunc());

    var systems = new Systems(nameof(HiroChallengesCoordinator), monitor, storage, logger);
    systems.Add(nakamaSystem);
    systems.Add(new ChallengesSystem(logger, nakamaSystem));
    // We need to register the EconomySystem to power rewards and the wallet
    systems.Add(new EconomySystem(logger, nakamaSystem, EconomyStoreType.Unspecified));
    return Task.FromResult(systems);
}
```

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

### Controller (`ChallengesController.cs`)

Coordinates between the UI and Hiro Challenges API. Subscribes to view events, manages challenge state, and executes game logic by calling the Challenges system.

**Challenge templates (game modes)**

```csharp
// Load challenge templates, which are configured on the server
public async Task<List<string>> LoadChallengeTemplates()
{
    _challengeTemplates.Clear();
    var loadedTemplates = (await _challengesSystem.GetTemplatesAsync()).Templates;
    var challengeTemplateNames = new List<string>();

    foreach (var template in loadedTemplates)
    {
        _challengeTemplates[template.Key] = template.Value;
        challengeTemplateNames.Add(
            template.Value.AdditionalProperties.TryGetValue("display_name", out var displayName)
                ? displayName
                : template.Key);
    }

    return challengeTemplateNames;
}
```

**Challenge discovery**

```csharp
// List challenges the user has joined or was invited to
var userChallengesResult = await _challengesSystem.ListChallengesAsync(null);

// Get detailed challenge info including participant scores (leaderboard)
var detailedChallenge = await _challengesSystem.GetChallengeAsync(challengeId, includeScores: true);
```

**Challenge lifecycle**

```csharp
// Create a challenge from a template. Parameters defined separately
var newChallenge = await _challengesSystem.CreateChallengeAsync(
    selectedTemplate.Key,
    challengeName,
    description ?? "Missing description.",
    inviteeIDs,
    isOpen,
    selectedTemplate.Value.MaxNumScore,
    delay,
    duration,
    maxParticipants,
    category ?? "Missing category",
    new Dictionary<string, string>()
);

// Player actions
await _challengesSystem.JoinChallengeAsync(_selectedChallenge.Id);
await _challengesSystem.InviteChallengeAsync(_selectedChallenge.Id, userIds: inviteeIDs);
await _challengesSystem.LeaveChallengeAsync(_selectedChallenge.Id);
await _challengesSystem.ClaimChallengeAsync(_selectedChallenge.Id);
```

**Scoring and rewards**

```csharp
// Submit a score with optional subscore and metadata
await _challengesSystem.SubmitChallengeScoreAsync(
    _selectedChallenge.Id,
    score,
    subScore,
    metadata,
    true
);

// Claim rewards when the challenge ends
await _challengesSystem.ClaimChallengeAsync(_selectedChallenge.Id);
await _economySystem.RefreshAsync();  // Update wallet UI with rewards
```

API reference: [Challenges](../../../hiro/unity/challenges/)

### Challenges view (`ChallengesView.cs`)

Manages the main UI layer for the challenges screen, including lists, modals, and buttons. Provides an event-based interface that the controller subscribes to for responding to player interaction.

### Challenge view (`ChallengeView.cs`)

Binds challenge data to UI elements for the challenges list. Displays name, category, participant count, status (pending/active/ended), and end time.

### Participant view (`ChallengeParticipantView.cs`)

Binds participant score data to UI elements. Displays username, score, subscore, rank, and submission count (e.g., "2/3" means 2 scores submitted out of 3 allowed).
