Using C# wrappers for GDK APIs in your Unity project
Use this topic to understand how to use API wrappers to properly call Microsoft Game Development Kit (GDK) and Xbox services APIs from managed code.
Accessing Microsoft Game Development Kit (GDK) APIs
After you've imported the GDK Unity package, its functionality is available under the XGamingRuntime
namespace. All Gaming Runtime APIs are available via static methods on the SDK
class. All Xbox services APIs are available via static methods on the SDK.XBL
class. The following example shows this availability.
using System;
// The namespace under which the "GDK" functionality is available.
using XGamingRuntime;
namespace TestGame
{
static class Program
{
static void Main()
{
// All APIs are accessed through static methods on the SDK class.
Int32 hr = SDK.XGameRuntimeInitialize();
// All Xbox services APIs are accessed through static methods on the SDK.XBL class.
Int32 hr = SDK.XBL.XblInitialize(SCID);
...
}
}
}
API coverage and conventions
Note
Not every API is available via the package. For a complete list of these APIs, see the Microsoft Game Development Kit (GDK) and Xbox services API lists later in this topic.
Conventions:
- API names match their GDK counterparts where possible.
- No exceptions. Errors are communicated via HRESULTs.
- Flat API surface with no object oriented encapsulation.
out
parameters are used in APIs that set parameters.- Async methods use
callbacks
. For details, see the following section.
Asynchronous programming model
All async APIs take a callback
as their last parameter. An example is shown as follows.
using System;
using XGamingRuntime;
class SignInManager
{
public void AddUser()
{
SDK.XUserAddAsync(XUserAddOptions.None, this.OnUserAddComplete);
}
private void OnUserAddComplete(Int32 hresult, XUserHandle userHandle)
{
// Check the result, and then do something with the handle.
}
}
Information about the threading model is as follows.
- Async methods execute immediately, and the work is performed on an available thread in the thread pool.
- The thread pool is initialized internally after a call is made to
SDK.XGameRuntimeInitialize()
. - No thread pool configuration options are exposed.
- The thread pool is initialized internally after a call is made to
- The result
callback
is invoked afterdispatch
is called (that is,SDK.XTaskQueueDispatch()
). As a result, it's important thatdispatch
is called frequently—ideally, during your game's update loop. - The result
callback
is executed on the thread that invokeddispatch
.
Example differences between native APIs and managed wrappers
Native APIs and managed wrappers have minimal differences. For reference, the following two examples show signature and call functions of XUserAddAsync
and XblAchievementsUpdateAchievementAsync
in managed and native code.
XUserAddAsync example
The native signature for XUserAddAsync
is as follows.
STDAPI XUserAddAsync(
_In_ XUserAddOptions options,
_Inout_ XAsyncBlock* async
) noexcept;
STDAPI XUserAddResult(
_Inout_ XAsyncBlock* async,
_Out_ XUserHandle* newUser
) noexcept;
Where the managed signature for XUserAddAsync
is:
public static void XGamingRuntime.SDK.XUserAddAsync(
XUserAddOptions options,
XUserAddCompleted completionRoutine
);
public delegate void XUserAddCompleted(Int32 hresult, XUserHandle userHandle);
An example of how to call functions of XUserAddAsync
in native code is as follows.
auto asyncBlock = std::make_unique<XAsyncBlock>();
ZeroMemory(asyncBlock.get(), sizeof(*asyncBlock));
asyncBlock->queue = _queue;
asyncBlock->context = this;
asyncBlock->callback = [](XAsyncBlock* ab)
{
auto asyncBlock = std::unique_ptr<XAsyncBlock>(ab);
XUserHandle user;
RETURN_IF_FAILED(XUserAddResult(ab, &user));
};
if (SUCCEEDED_LOG(XUserAddAsync(
XUserAddOptions::AddDefaultUserAllowingUI,
asyncBlock.get())))
{
// The call succeeded, so release the std::unique_ptr ownership of XAsyncBlock* because the callback will take over ownership.
// If the call fails, the std::unique_ptr will keep ownership and delete the XAsyncBlock*
asyncBlock.release();
}
Where the managed example of calling XUserAddAsync
functions is:
Managed add user
SDK.XUserAddAsync(
XUserAddOptions.AddDefaultUserAllowingUI,
(hr, userHandle) =>
{
LOG("XUserAddAsync", hr);
if (hr >= 0)
{
this.userHandle = userHandle;
// Sign-in succeeded.
}
else
{
// Sign-in failed.
}
}
);
XblAchievementsUpdateAchievementAsync example
The native signature for XblAchievementsUpdateAchievementAsync
is as follows.
STDAPI XblAchievementsUpdateAchievementAsync(
_In_ XblContextHandle xboxLiveContext,
_In_ uint64_t xboxUserId,
_In_z_ const char* achievementId,
_In_ uint32_t percentComplete,
_In_ XAsyncBlock* async
) XBL_NOEXCEPT;
Where the managed signature for XblAchievementsUpdateAchievementAsync
is:
public static void XGamingRuntime.SDK.XBL.XblAchievementsUpdateAchievementAsync(
XblContextHandle xboxLiveContext,
UInt64 xboxUserId,
string achievementId,
UInt32 percentComplete,
XblAchievementsUpdateAchievementResult completionRoutine);
public delegate void XblAchievementsUpdateAchievementResult(Int32 hresult);
An example of how to call functions of XblAchievementsUpdateAchievementAsync
in native code is as follows.
auto asyncBlock = std::make_unique<XAsyncBlock>();
asyncBlock->queue = Data()->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))
{
// Achievement updated.
}
else if (result == HTTP_E_STATUS_NOT_MODIFIED)
{
// Achievement isn't modified.
}
else
{
// Achievement failed to update.
}
};
HRESULT hr = XblAchievementsUpdateAchievementAsync(
Data()->xboxLiveContext,
Data()->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, the std::unique_ptr will keep ownership and delete the XAsyn-cBlock*
asyncBlock.release();
}
Where the managed example of calling XblAchievementsUpdateAchievementAsync
functions is:
SDK.XBL.XblAchievementsUpdateAchievementAsync(
xblContextHandle,
xboxUserId,
achievementId,
percentComplete
(achievementUpdateResult) => {
LOG("XblAchievementsUpdateAchievementAsync result", achievementUpdateResult);
if (achievementUpdateResult == 0)
{
// Achievement updated.
}
else if (achievementUpdateResult == HTTP_E_STATUS_NOT_MODIFIED) // 0x80190130
{
// Achievement isn't modified.
}
else
{
// Achievement failed to update.
}
}
);
Initializing Xbox Services API (XSAPI) in managed code
For reference, the following is an initialization of XSAPI in managed code. This is the XSAPI signature in managed code.
public static Int32 XGamingRuntime.SDK.XBL.XblInitialize(string scid)
The following is an example of the XSAPI call pattern in managed code.
Int32 hresult = SDK.XBL.XblInitialize(SCID);
List of Microsoft Game Development Kit (GDK) APIs in managed wrappers
The following Microsoft Game Development Kit (GDK) APIs are included in managed wrappers within the GDK Unity package. For more information about Microsoft Game Development Kit (GDK) APIs, see System API reference.
- XAccessibility
- XClosedCaptionGetProperties
- XClosedCaptionSetEnabled
- XHighContrastGetMode
- XSpeechToTextSendString
- XSpeechToTextSetPositionHint
- XSpeechToTextBeginHypothesisString
- XSpeechToTextUpdateHypothesisString
- XSpeechToTextFinalizeHypothesisString
- XSpeechToTextCancelHypothesisString
- XGame
- XGameGetXboxTitleId
- XGameInvite
- XGameInviteRegisterForEvent
- XGameInviteUnregisterForEvent
- XGameSave
- XGameSaveInitializeProvider
- XGameSaveInitializeProviderAsync
- XGameSaveCloseProvider
- XGameSaveGetRemainingQuota
- XGameSaveGetRemainingQuotaAsync
- XGameSaveDeleteContainer
- XGameSaveDeleteContainerAsync
- XGameSaveCreateContainer
- XGameSaveCloseContainer
- XGameSaveGetContainerInfo
- XGameSaveEnumerateContainerInfo
- XGameSaveEnumerateContainerInfoByName
- XGameSaveEnumerateBlobInfo
- XGameSaveEnumerateBlobInfoByName
- XGameSaveReadBlobData
- XGameSaveReadBlobDataAsync
- XGameSaveCreateUpdate
- XGameSaveCloseUpdateHandle
- XGameSaveSubmitBlobWrite
- XGameSaveSubmitBlobDelete
- XGameSaveSubmitUpdate
- XGameSaveSubmitUpdateAsync
- XGameUI
- XGameUiShowAchievementsAsync
- XGameUiShowMessageDialogAsync
- XGameUiShowErrorDialogAsync
- XGameUiShowTextEntryAsync
- XGameUiSetNotificationPositionHint
- XGameUiShowSendGameInviteAsync
- XGameUIShowWebAuthenticationAsync
- XGameUiShowPlayerProfileCardAsync
- XGameUiShowPlayerPickerAsync
- XLauncher
- XLaunchUri
- XPackage
- XPackageGetCurrentProcessPackageIdentifier
- XPackageIsPackagedProcess
- XPackageGetUserLocale
- XPackageEnumeratePackages
- XPackageRegisterPackageInstalled
- XPackageUnregisterPackageInstalled
- XPackageEnumerateFeatures
- XPackageMount
- XPackageGetMountPath
- XPackageCloseMountHandle
- XPackageCreateInstallationMonitor
- XPackageCloseInstallationMonitorHandle
- XPackageGetInstallationProgress
- XPackageUpdateInstallationMonitor
- XPackageRegisterInstallationProgressChanged
- XPackageUnregisterInstallationProgressChanged
- XPackageEstimateDownloadSize
- XPackageGetWriteStats
- XPackageUninstallUWPInstance
- XStore
- XStoreCreateContext
- XStoreCloseContextHandle
- XStoreIsAvailabilityPurchasable
- XStoreAcquireLicenseForPackageAsync
- XStoreCanAcquireLicenseForPackageAsync
- XStoreCanAcquireLicenseForStoreIdAsync
- XStoreCloseLicenseHandle
- XStoreIsLicenseValid
- XStoreQueryAddOnLicensesAsync
- XStoreQueryGameLicenseAsync
- XStoreQueryLicenseTokenAsync
- XStoreRegisterGameLicenseChanged
- XStoreRegisterPackageLicenseLost
- XStoreUnregisterGameLicenseChanged
- XStoreUnregisterPackageLicenseLost
- XStoreAcquireLicenseForDurablesAsync
- XStoreQueryGameAndDlcPackageUpdatesAsync
- XStoreDownloadAndInstallPackagesAsync
- XStoreDownloadAndInstallPackageUpdatesAsync
- XStoreDownloadPackageUpdatesAsync
- XStoreQueryPackageIdentifier
- XStoreShowRedeemTokenUIAsync
- XStoreShowRateAndReviewUIAsync
- XStoreShowPurchaseUIAsync
- XStoreQueryConsumableBalanceRemainingAsync
- XStoreReportConsumableFulfillmentAsync
- XStoreGetUserCollectionsIdAsync
- XStoreGetUserPurchaseIdAsync
- XStoreQueryAssociatedProductsAsync
- XStoreQueryEntitledProductsAsync
- XStoreQueryProductForCurrentGameAsync
- XStoreQueryProductForPackageAsync
- XStoreQueryProductsAsync
- XStoreProductsQueryNextPageAsync
- XStoreCloseProductsQueryHandle
- XThread
- XThreadIsTimeSensitive
- XThreadSetTimeSensitive
- XThreadAssertNotTimeSensitive
- XUser
- XUserDuplicateHandle
- XUserCloseHandle
- XUserCompare
- XUserGetMaxUsers
- XUserAddAsync
- XUserGetId
- XUserFindUserById
- XUserGetLocalId
- XUserFindUserByLocalId
- XUserGetIsGuest
- XUserGetState
- XUserGetGamertag
- XUserGetGamerPictureAsync
- XUserGetAgeGroup
- XUserCheckPrivilege
- XUserResolvePrivilegeWithUiAsync
- XUserGetTokenAndSignatureUtf16Async
- XUserResolveIssueWithUiUtf16Async
- XUserRegisterForChangeEvent
- XUserUnregisterForChangeEvent
- XUserCloseSignOutDeferralHandle
List of Xbox services APIs in managed wrappers
The following Xbox services APIs are included in managed wrappers within the GDK Unity package. For more information about Xbox services APIs, see Xbox Live API reference.