Updating title-managed Achievements

This topic covers the following:

Unlocking an achievement

After your achievements are configured via Partner Center and published to your development sandbox, your title can unlock them by calling the XblAchievementsUpdateAchievementAsync API. For more information, see the example code in the next section.

To unlock an achievement, set percentComplete to 100. If the user is online, the request is immediately sent to the Xbox services Achievements service and triggers the following user experiences.

  • The user receives an Achievement Unlocked notification.
  • The specified achievement appears as unlocked in the user's achievement list for the title.
  • The unlocked achievement is added to the user's activity feed.

Note

The user experience is visually the same for achievements that use either event-based Achievements or title-managed Achievements.

If the user is offline, the unlock request is queued locally on the user's device. When it has reestablished network connectivity, the request is automatically sent to the Achievements service (no action is required from the game to trigger this), and the previous user experiences occur as described.

Updating completion progress for an achievement

To update a user's progress toward unlocking an achievement, call XblAchievementsUpdateAchievementAsync. Set the percentComplete argument to a whole number between 1–100. For more information, see the following example code.

An achievement's progress can only increase. If percentComplete is set to a number less than the achievement's last percentComplete value, the update is ignored. For example, if the achievement's percentComplete had previously been set to 75, sending an update with a value of 25 is ignored. The achievement is still displayed as 75 percent complete.

If percentComplete is set to 100, the achievement is unlocked.

If percentComplete is set to a number greater than 100, the API behaves as if you set the number to exactly 100.

Updating achievements for the current title

You can update achievements for the current title by calling XblAchievementsUpdateAchievementAsync, as follows.

Flat C API

auto asyncBlock = std::make_unique<XAsyncBlock>();
asyncBlock->queue = queue;
asyncBlock->context = nullptr;
asyncBlock->callback = [](XAsyncBlock* asyncBlock)
{
    std::unique_ptr<XAsyncBlock> asyncBlockPtr{ asyncBlock }; // Take over ownership of the XAsyncBlock*.
    auto result = XAsyncGetStatus(asyncBlock, false);
    if (SUCCEEDED(result))
    {
        // The achievement was updated.
    }
    else if (result == HTTP_E_STATUS_NOT_MODIFIED)
    {
        // The achievement wasn't updated.
    }
    else
    {
        // The achievement failed to update.
    }
};

HRESULT hr = XblAchievementsUpdateAchievementAsync(
    xboxLiveContext,
    xboxUserId,
    achievementId.c_str(),
    percentComplete,
    asyncBlock.get()
);
if (SUCCEEDED(hr))
{
    // The call succeeded, so release the std::unique_ptr ownership of XAsyncBlock* because the callback will take over ownership.
    // If the call fails, std::unique_ptr will keep ownership and delete XAsyncBlock*.
    asyncBlock.release();
}

For more information, see the following:

Updating achievements for a different title

You can update achievements for another titleId by using XblAchievementsUpdateAchievementForTitleIdAsync, as follows.

Flat C API

auto asyncBlock = std::make_unique<XAsyncBlock>();
asyncBlock->queue = queue;
asyncBlock->context = nullptr;
asyncBlock->callback = [](XAsyncBlock* asyncBlock)
{
    std::unique_ptr<XAsyncBlock> asyncBlockPtr{ asyncBlock }; // Take over ownership of the XAsyncBlock*.
    auto result = XAsyncGetStatus(asyncBlock, false);
    if (SUCCEEDED(result))
    {
        // The achievement was updated.
    }
    else if (result == HTTP_E_STATUS_NOT_MODIFIED)
    {
        // The achievement wasn't updated.
    }
    else
    {
        // The achievement failed to update.
    }
};

HRESULT hr = XblAchievementsUpdateAchievementForTitleIdAsync(
    xboxLiveContext,
    xboxUserId,
    titleId,
    scid,
    achievementId.c_str(),
    percentComplete,
    asyncBlock.get()
);
if (SUCCEEDED(hr))
{
    // The call succeeded, so release the std::unique_ptr ownership of XAsyncBlock* because the callback will take over ownership.
    // If the call fails, std::unique_ptr will keep ownership and delete XAsyncBlock*.
    asyncBlock.release();
}

For more information, see the following:

Return to the top of this topic.