# Achievements

**URL:** https://heroiclabs.com/docs/hiro/unity/achievements/
**Summary:** Achievements are a way to reward players for completing specific tasks in your game.
**Keywords:** achievement, player progression
**Categories:** hiro, unity, achievements

---


# Achievements

Read more about the Achievements system in Hiro [here](../../concepts/achievements/).

## Initializing the achievements system

The achievements system relies on the [Nakama System](../getting-started/nakama-system) and an `ILogger`, both must be passed in as dependencies via the constructor.

```csharp
var achievementsSystem = new AchievementsSystem(logger, nakamaSystem);
systems.Add(achievementsSystem);
```

## Subscribing to changes in the achievements system

You can listen for changes in the achievements system so that you can respond appropriately, such as updating the UI, by implementing the `IObserver` pattern, or use the `SystemObserver<T>` type which handles it for you.

```csharp
var disposer = SystemObserver<AchievementsSystem>.Create(achievementsSystem, system => {
    Instance.Logger.Info($"System updated.");

    // Update UI elements etc as necessary here...
});
```

## Refreshing the achievements system

To ensure the achievements system has the latest information from Nakama you can refresh it.

```csharp
await achievementsSystem.RefreshAsync();
```

## Listing achievements

You can list all achievements for the user.

```csharp
foreach (var achievement in achievementsSystem.GetAchievements())
{
    Debug.Log($"Achievement {achievement.Name} ({achievement.Category})");
    Debug.Log(achievement.Description);

    if (achievement.HasReward())
    {
        Debug.Log("Reward available on completion");
    }

    if (achievement.SubAchievements.Any())
    {
        Debug.Log($"{achievement.SubAchievements.Count} sub-achievements.");
    }
}
```

You can also list all repeatable achievements for the user.

```csharp
foreach (var achievement in achievementsSystem.GetRepeatAchievements())
{
    // ...
}
```

As well as list achievements by category for the user.

```csharp
foreach (var achievement in achievementsSystem.GetAchievements("<categoryName>"))
{
    // ...
}
```
## Listing active achievements

Filter achievements to show only those currently in an active time window using the `IsActive` field.

```csharp
var activeAchievements = achievementsSystem.GetAchievements()
    .Where(a => a.IsActive);

foreach (var achievement in activeAchievements)
{
    Debug.Log($"Active achievement: {achievement.Name} ({achievement.Count}/{achievement.MaxCount})");
}
```

To filter by category at the same time, pass the category name to `GetAchievements`.

```csharp
var activeInCategory = achievementsSystem.GetAchievements("<categoryName>")
    .Where(a => a.IsActive);
```


> **Note:** `IsActive` reflects whether the achievement is within its configured time window (start/end times, reset period, duration). It's separate from `GetAvailableAchievements`, which filters by precondition completion.

## Listing available achievements by category

Similarly to above, you can list achievements by category for the user, including only achievements the user is currently able to complete.

```csharp
foreach (var achievement in achievementsSystem.GetAvailableAchievements("<categoryName">))
{
    // ...
}
```

## Updating achievement progress

You can update the user's progress for achievements, passing in the each individual achievement's progress.

```csharp
var updates = new Dictionary<string, long>
{
    { "<achievementId1>", 1 }
    { "<achievementId2>", 2 }
};
await achievementsSystem.UpdateAchievementsAsync(updates);
```

Alternatively, you can update multiple achievements by the same amount using this function overload.

```csharp
var updates = new[]
{
    "<achievementId1>",
    "<achievementId2>"
};
await achievementsSystem.UpdateAchievementsAsync(updates, 1);
```

## Claiming achievement rewards

You can claim rewards for an achievement. You can also specify whether you would like to claim any available total rewards (e.g. if the user has completed all sub-achievements) If you are granting rewards to the player from completing an achievement, you should refresh the EconomySystem here to get the updated state.

```csharp
var claimTotalReward = true;

await achievementsSystem.ClaimAchievementsAsync(new[] {"<achievementId1>", "<achievementId2>}", claimTotalReward);

// Get updated economy after rewards have been granted
await economySystem.RefreshAsync();
```

## Additional information

- [Hiro Achievements sample project](../../../../sample-projects/unity/hiro-achievements/)
- [Mage Mayhem sample project](../../../../sample-projects/games/mage-mayhem/)