Skip to main content
Steamworks and the XBOX Game Development Kit (GDK) have a number of differences in structure, patterns in their APIs, and purpose. They are outlined in this topic.

No API singleton in the XBOX Game Development Kit (GDK)

Steamworks follows a pattern where each API feature set is defined as an interface (for example, all the user statistics functions are in the ISteamUserStats interface and remote storage is in ISteamRemoteStorage), instances of which are made available as soon as the API is initialized by the game in code. The Steamworks API singleton that gets initialized at game start provides these functions and keeps track of state throughout the lifetime of the application. This isn’t the case with the XBOX Game Development Kit (GDK) APIs, which favor a C API where much of the context and current state of the API data must be kept by the game itself and passed into the various API functions. For instance, after authenticating a user with XBOX services, the game must keep the XBOX services context handle and a user handle. The APIs used to get this information don’t “remember” them throughout the lifetime of your games like Steamworks does. Therefore, you need to add member variables to your game class or otherwise keep track of these handles in your game.

Asynchronous functions and callbacks

Asynchronous functions in Steamworks trigger events that you can subscribe to with the STEAM_CALLBACK macro or a CCallResult variable. When an event corresponding to the specified event struct type is fired, the specified method is called and provided an event struct as its sole argument. This struct contains the result returned by the API as well as previously available contextual information that might be needed to handle the results of the call. For example, calling ISteamUserStats::DownloadLeaderboardEntries, you need a SteamLeaderboard_t handle in the callback function to pass to ISteamUserStats::DownloadLeaderboardEntries, which you can get as a member of the LeaderboardScoresDownloaded_t struct passed as a parameter to the callback method that you defined. In the XBOX Game Development Kit (GDK), all asynchronous actions follow a different pattern: you create an XAsyncBlock struct, optionally assign it to a task queue, and then call the async API method. After that API call is completed, it fires the callback function that’s defined as a member of the XAsyncBlock and provides a pointer to the async block as the sole argument. If you need to access information inside the callback function, you can use the context pointer member of the async block to do so. Unlike Steam, the information in this context struct isn’t provided automatically—you need to build it yourself. Using our previous example, if you needed access to a set of data in your callback function, you could do the following as shown in this code example.
The previous example also includes a pointer to this via shared_from_this() so that the callback function has the ability to call instance methods or access member variables if needed. Be very careful when passing raw pointers due to lifetime issues. Also note that if you only need access to one variable in your callback, you can simply set the value of your async block’s context pointer to be a pointer to that value, and then cast to that value’s type in your callback instead of needing to define a struct.
Steamworks also requires the game’s code to fire callbacks on some interval by using the SteamAPI_RunCallbacks function. This isn’t necessary in the XBOX Game Development Kit (GDK). Callbacks are triggered after the asynchronous task that’s dispatched by its task queue is completed if using a thread pool task queue, which is the default. For more control, you can dispatch the asynchronous task manually to a specific thread by calling XTaskQueueDispatch when using a manual task queue. This is more complex, and details about how this is done are outside the scope of this guide. For more information about how the XBOX Game Development Kit (GDK) handles asynchronous API operations, including a code sample, see Asynchronous Programming Model.

Source of truth for title-managed APIs

With Steamworks, the API is the single source of truth for pretty much every value that touches it. User stats are fetched from the API and calculated based on the values from ISteamUserStats::GetStat/ISteamUserStats::SetStat, for instance, and you aren’t required to store these values elsewhere yourself. The achievements and stats/leaderboards APIs in the XBOX Game Development Kit (GDK) both have an option to be title-managed for developers wanting more flexibility and simplicity in the calls that they need to make. Title-managed API’s values are, as the name suggests, managed by your title. The single source of truth for these values is your game, which can store the values anywhere—for example, a save file, cloud storage, or a third-party backend server. The value stored on the XBOX network (also known as XBOX Live) servers can be used as a snapshot to which you occasionally make updates, but it shouldn’t be your single source of truth at runtime. An alternative option to title-managed stats/achievements are event-based stats/achievements. These use telemetry events to update a user’s achievement progress or recalculate their stats, and they consider XBOX services as their source of truth. You can choose which API you want to use for stats and achievements in the Gameplay Setting page for your game in Partner Center. For more information about this, see the descriptions in the topics that compare Event-based vs. title-managed Stats and Event-based vs. title-managed Achievements. You might sometimes see these APIs referred to by their previous names of Stats/Achievements 2013 (event-based) and Stats/Achievements 2017 (title-managed).

XBOX Game Development Kit (GDK) is multiplatform

Games that make use of the Steamworks APIs can assume that they’re always launched through Steam, and therefore the API can inject some context at initialization about who is playing the game. Games using the XBOX Game Development Kit (GDK) can be used by games running on an XBOX console, on a PC by using the XBOX Gaming App, or on any number of devices and launchers. Therefore, some context that is automatically available with Steam might need to be manually initialized with the XBOX Game Development Kit (GDK), such as the user’s identity. To gain access to this information, you can follow the steps in the Initializing the GDK topic in this guide, which provides instructions for authenticating a user with their Microsoft account/gamertag. This also means that there are some paradigms in the XBOX Game Development Kit (GDK)‘s functions that are tailored to console scenarios, like multiple user sign-in support for the XUser APIs, that don’t have an analog on the PC.

Packaging

Most games on Steam can use the Steamworks API functions by simply setting up the game information in the Steamworks admin portal, downloading the SDK, importing the required files, and initializing the API in code. After doing these steps, your game integrates with the Steamworks API from anywhere it’s launched, such as a game engine editor. For the XBOX Game Development Kit (GDK) APIs to work, your game must first be packaged. To correctly package your game, you need to edit your game’s MicrosoftGame.config file and use the MakePkg tool from the XBOX Game Development Kit (GDK) to create the MSIXVC package for your game, which you can then sideload as a Microsoft Store app on a PC that has enabled Developer Mode. This also means that, unlike Steamworks games, some of the XBOX Game Development Kit (GDK) functionality doesn’t work in a game engine editor or other development-time environments without first packaging the game. For more information about packaging, see the following resources.

Developing and testing Unity games

Games built with the Unity game engine can use the GDK Unity Plug-in to develop their titles. This plug-in is included in the XBOX Game Development Kit (GDK) offering and as a stand-alone add-in on the XBOX Developer Downloads portal. This plug-in includes API wrappers that allow you to call XBOX Game Development Kit (GDK) functions in your game’s C# code. For more information about the GDK Unity Plug-in, please see Get started with Unity for PC development.
Last modified on August 21, 2026