Getting Started with the C# SDK

Overview of the EOS C# SDK

Epic Online Services (EOS) features a C# SDK in addition to the C SDK. This document will help you integrate EOS with your project using the C# SDK, and will cover some of the implementation differences between the two. While the core functionality remains the same regardless of which SDK you use, the C# SDK differs in design in the following ways:

  • The C# SDK adheres to C# best practices and follows an object-oriented approach, such as using handle objects rather than C-style handles to manage asynchronous operations.

  • Naming conventions match typical C# patterns. For example, the EOS_Auth_Login in the C SDK is accessible in the C# SDK as Epic.OnlineServices.Auth.AuthInterface.Login.

  • Data structures in the C SDK require macro-based API version numbers to ensure compatibility; these values are pre-populated in the C# SDK.

At this time, the C# SDK has only been tested on desktop platforms.

Getting Started

Before you begin, you'll need to download the C# SDK. You'll also need to set up a product on Epic's Developer Portal and collect some identifying data about it. The SDK needs the following product information from the Developer Portal:

  • Product ID

  • Sandbox ID

  • Deployment ID

  • Client ID

  • Client secret

When you start integrating the EOS SDK, these values will enable you to create the Platform Interface, which is required to access all other EOS SDK interfaces. Once you have this information, you can proceed to integrate the SDK with your product.

General Integration

  1. Include the C# SDK source files in your project.

  2. Ensure that the appropriate library binary file for your target platform is accessible by your application. For example, a Windows x64 integration would use EOSSDK-Win64-Shipping.dll.

  3. The C# SDK determines which library binary name to target in Epic.OnlineServices.Config. Several platforms have been preconfigured to point to the correct name for convenience. If your target platform has not been preconfigured, make the appropriate changes to the configuration and your project symbols to avoid a build error. For example, you may need to set PLATFORM_64BITS if targeting Windows x64, or PLATFORM_32BITS if targeting Windows x86.

Unity Integration

  1. Copy the C# SDK source files into the Assets folder. You must include both the Core and Generated folders.

  2. Copy the appropriate library binary file into the Assets folder for your target platform. For example, projects targeting Windows x64 would include EOSSDK-Win64-Shipping.dll.

  3. The C# SDK determines which library binary name to target in Epic.OnlineServices.Config. Several platforms have been preconfigured to point to the correct name for convenience. If your target platform has not been preconfigured, make the appropriate changes to the configuration and your project symbols to avoid a build error.

  4. Create a new script to control the SDK. In this document, we have used the name EOSSDKComponent.

    New script Component

  5. Add the component to an entity so it will be created when the game needs it. For demonstration purposes, we have added it to the Main Camera.

    Add Component

  6. Write your EOS SDK code in this component. We have provided some sample code in this document for demonstration purposes.

Implementing the SDK

Once you have set up your product and integrated the C# SDK, you can begin writing code. You'll need to initialize the SDK, call its Tick method regularly to ensure that the SDK can execute and that callbacks can run, and shut it down when your application finishes.

Managing the SDK's Life Cycle

There are three main parts of the SDK's life cycle: Initialization, Ticking (normal operation), and Shutdown.

Initialization

The Platform Interface is the entry point to the SDK, and you will need an instance of this interface to use EOS. To create one, call Epic.OnlineServices.Platform.PlatformInterface.Initialize with some basic information about your application, then call Epic.OnlineServices.Platform.PlatformInterface.Create with the values you have obtained from the Developer Portal to get an Epic.OnlineServices.Platform.PlatformInterface instance. Store this instance; you will need it to interact with the SDK.

You can only initialize the SDK once; subsequent calls to Epic.OnlineServices.Platform.PlatformInterface.Initialize will return the AlreadyInitialized failure code. We recommend initializing the SDK when your application starts up and not releasing it until the application shuts down.

Ticking

In order for the SDK to operate, you must call Epic.OnlineServices.Platform.PlatformInterface.Tick on your Platform Interface instance regularly. These calls do not need to happen every frame, but should happen fairly often; one call every 100 milliseconds is considered reasonable, but you can adjust the exact frequency to your needs. SDK callbacks can only run when you call Tick, so all of your asynchronous operations depend on it.

Shutdown

When you no longer need the SDK — generally, at application shutdown time — you can shut it down by calling Epic.OnlineServices.Platform.PlatformInterface.Release to release your Platform Interface instance, and then Epic.OnlineServices.Platform.PlatformInterface.Shutdown to complete the shutdown process. This process is final; Epic.OnlineServices.Platform.PlatformInterface.Release puts the SDK into a finalized state, and you cannot acquire another Platform Interface handle or reinitialize the SDK after that point. For this reason, we advise against shutting down the EOS SDK until application shutdown.

Some editor environments, including Unity, load external libraries like EOS during editor startup and do not unload them until the editor shuts down. In these cases, you should not call Epic.OnlineServices.Platform.PlatformInterface.Release or Epic.OnlineServices.Platform.PlatformInterface.Shutdown at the end of an in-editor play session, because you will be unable to initialize the SDK successfully in any future session without restarting the editor. In addition, because these editor environments use one continuous instance of the SDK, operations that began right before the end of a play session could finish and trigger callbacks in the following session.

Results

Most callback data structures and some return values use Epic.OnlineServices.Result to convey the results of SDK operations. Make sure to use this to handle errors and ensure operations are performing as expected.

Logging

The SDK outputs useful debugging information through an internal interface. To enable this feature, set up Epic.OnlineServices.Logging.LoggingInterface as early as possible, preferably immediately after initializing the SDK, by calling Epic.OnlineServices.Logging.LoggingInterface.SetLogLevel with parameters indicating the level of detail you require, followed by Epic.OnlineServices.Logging.LoggingInterface.SetCallback with a callback function to receive log information. This feature can provide insight into internal operations and can help with identifying the causes of unexpected behaviors you may encounter.

Unmanaged Memory

The SDK uses objects with an underlying type of Epic.OnlineServices.Handle. In some cases, these objects act as accessors to unmanaged data in the SDK's cache, with application-controlled lifetimes. These objects have Release methods that you must call to prevent memory leaks. For example, the Epic.OnlineServices.Presence.PresenceModification object that you get from Epic.OnlineServices.Presence.PresenceInterface.CreatePresenceModification has a Release method that you must call when you no longer need the object.

Threading

The C# SDK is not currently thread safe. We recommend that all calls to the SDK come from your application's main thread. At this time, we recommend against using async, await, Thread, Task, or similar patterns.

Sample Projects

The C# SDK ships with sample projects that demonstrate various features and can help you get started faster.

Sample Code

The sample code in this section is intended to demonstrate and help familiarize you with the C# SDK.

Setting up the Platform

// Set these values as appropriate. For more information, see the Developer Portal documentation.
string productName = "MyApplication";
string productVersion = "1.0";
string productId = "";
string sandboxId = "";
string deploymentId = "";
string clientId = "";
string clientSecret = "";

var initializeOptions = new Epic.OnlineServices.Platform.InitializeOptions()
{
    ProductName = productName,
    ProductVersion = productVersion
};

var initializeResult = Epic.OnlineServices.Platform.PlatformInterface.Initialize(initializeOptions);
if (initializeResult != Epic.OnlineServices.Result.Success)
{
    throw new System.Exception("Failed to initialize platform: " + initializeResult);
}

// The SDK outputs lots of information that is useful for debugging.
// Make sure to set up the logging interface as early as possible: after initializing.
Epic.OnlineServices.Logging.LoggingInterface.SetLogLevel(Epic.OnlineServices.Logging.LogCategory.AllCategories, LogLevel.VeryVerbose);
Epic.OnlineServices.Logging.LoggingInterface.SetCallback((Epic.OnlineServices.Logging.LogMessage logMessage) =>
{
    Console.WriteLine(logMessage.Message);
});

var options = new Options()
{
    ProductId = productId,
    SandboxId = sandboxId,
    DeploymentId = deploymentId,
    ClientCredentials = new ClientCredentials()
    {
        ClientId = clientId,
        ClientSecret = clientSecret
    }
};

var platformInterface = PlatformInterface.Create(options);
if (platformInterface == null)
{
    throw new System.Exception("Failed to create platform");
}

Logging In

var loginCredentialType = Epic.OnlineServices.Auth.LoginCredentialType.AccountPortal;
/// These fields correspond to <see cref="Epic.OnlineServices.Auth.Credentials.Id" /> and <see cref="Epic.OnlineServices.Auth.Credentials.Token" />,
/// and their use differs based on the login type. For more information, see <see cref="Epic.OnlineServices.Auth.Credentials" />
/// and the Auth Interface documentation.
var loginCredentialId = null;
var loginCredentialToken = null;

var authInterface = platformInterface.GetAuthInterface();
if (authInterface == null)
{
    throw new Exception("Failed to get auth interface");
}

var loginOptions = new Epic.OnlineServices.Auth.LoginOptions()
{
    Credentials = new Epic.OnlineServices.Auth.Credentials()
    {
        Type = loginCredentialType,
        Id = loginCredentialId,
        Token = loginCredentialToken
    }
};

// Ensure platform tick is called on an interval, or this will not callback.
authInterface.Login(loginOptions, null, (Epic.OnlineServices.Auth.LoginCallbackInfo loginCallbackInfo) =>
{
    if (loginCallbackInfo.ResultCode == Epic.OnlineServices.Result.Success)
    {
        Console.WriteLine("Login succeeded");
    }
    else
    {
        Console.WriteLine("Login returned " + loginCallbackInfo.ResultCode);
    }
});

Unity EOSSDK Component

// This code is provided for demonstration purposes and is not intended to represent ideal Unity practices.
using Epic.OnlineServices;
using Epic.OnlineServices.Auth;
using Epic.OnlineServices.Logging;
using Epic.OnlineServices.Platform;
using UnityEngine;

public class EOSSDKComponent : MonoBehaviour
{
    // Set these values as appropriate. For more information, see the Developer Portal documentation.
    public string m_ProductName = "MyApplication";
    public string m_ProductVersion = "1.0";
    public string m_ProductId = "";
    public string m_SandboxId = "";
    public string m_DeploymentId = "";
    public string m_ClientId = "";
    public string m_ClientSecret = "";

    public LoginCredentialType m_LoginCredentialType = LoginCredentialType.AccountPortal;
    /// These fields correspond to <see cref="Credentials.Id" /> and <see cref="Credentials.Token" />,
    /// and their use differs based on the login type. For more information, see <see cref="Credentials" />
    /// and the Auth Interface documentation.
    public string m_LoginCredentialId = null;
    public string m_LoginCredentialToken = null;

    private static PlatformInterface s_PlatformInterface;
    private const float c_PlatformTickInterval = 0.1f;
    private float m_PlatformTickTimer = 0f;

    void Start()
    {
        var initializeOptions = new InitializeOptions()
        {
            ProductName = m_ProductName,
            ProductVersion = m_ProductVersion
        };

        var initializeResult = PlatformInterface.Initialize(initializeOptions);

        // This code is called each time the game is run in the editor, so we catch the case where the SDK has already been initialized in the editor.
        var isAlreadyConfiguredInEditor = Application.isEditor && initializeResult == Result.AlreadyConfigured;
        if (initializeResult != Result.Success && !isAlreadyConfiguredInEditor)
        {
            throw new System.Exception("Failed to initialize platform: " + initializeResult);
        }

        // The SDK outputs lots of information that is useful for debugging.
        // Make sure to set up the logging interface as early as possible: after initializing.
        LoggingInterface.SetLogLevel(LogCategory.AllCategories, LogLevel.VeryVerbose);
        LoggingInterface.SetCallback((LogMessage logMessage) =>
        {
            Debug.Log(logMessage.Message);
        });

        var options = new Options()
        {
            ProductId = m_ProductId,
            SandboxId = m_SandboxId,
            DeploymentId = m_DeploymentId,
            ClientCredentials = new ClientCredentials()
            {
                ClientId = m_ClientId,
                ClientSecret = m_ClientSecret
            }
        };

        s_PlatformInterface = PlatformInterface.Create(options);
        if (s_PlatformInterface == null)
        {
            throw new System.Exception("Failed to create platform");
        }

        var loginOptions = new LoginOptions()
        {
            Credentials = new Credentials()
            {
                Type = m_LoginCredentialType,
                Id = m_LoginCredentialId,
                Token = m_LoginCredentialToken
            }
        };

        // Ensure platform tick is called on an interval, or this will not callback.
        s_PlatformInterface.GetAuthInterface().Login(loginOptions, null, (LoginCallbackInfo loginCallbackInfo) =>
        {
            if (loginCallbackInfo.ResultCode == Result.Success)
            {
                Debug.Log("Login succeeded");
            }
            else
            {
                Debug.Log("Login returned " + loginCallbackInfo.ResultCode);
            }
        });
    }

    // Calling tick on a regular interval is required for callbacks to work.
    private void Update()
    {
        if (s_PlatformInterface != null)
        {
            m_PlatformTickTimer += Time.deltaTime;

            if (m_PlatformTickTimer >= c_PlatformTickInterval)
            {
                m_PlatformTickTimer = 0;
                s_PlatformInterface.Tick();
            }
        }
    }

    // When you release and shutdown the SDK library, you cannot initialize it again.
    // Make sure this is done at a relevant time in your game's lifecycle.
    // If you are working in editor, it is advised you do not release and shutdown the SDK
    // as you would be required to restart Unity to initialize the SDK again.
    private void OnDestroy()
    {
        if (!Application.isEditor && s_PlatformInterface != null)
        {
            s_PlatformInterface.Release();
            s_PlatformInterface = null;
            PlatformInterface.Shutdown();
        }
    }
}