> ## Documentation Index
> Fetch the complete documentation index at: https://discord-platform-username.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Getting Started with Unity and the Discord Social SDK

> Integrate the Discord Social SDK into Unity games.

export const InboxIcon = props => <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path fill="currentColor" fill-rule="evenodd" d="M5 2a3 3 0 0 0-3 3v14a3 3 0 0 0 3 3h14a3 3 0 0 0 3-3V5a3 3 0 0 0-3-3H5ZM4 5.5C4 4.67 4.67 4 5.5 4h13c.83 0 1.5.67 1.5 1.5v6c0 .83-.67 1.5-1.5 1.5h-2.65c-.5 0-.85.5-.85 1a3 3 0 1 1-6 0c0-.5-.35-1-.85-1H5.5A1.5 1.5 0 0 1 4 11.5v-6Z" clip-rule="evenodd" /></svg>;

export const UserStatusIcon = props => <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path fill="currentColor" d="M16 6a4 4 0 1 1-8 0 4 4 0 0 1 8 0ZM2 20.53A9.53 9.53 0 0 1 11.53 11h.94c1.28 0 2.5.25 3.61.7.41.18.36.77-.05.96a7 7 0 0 0-3.65 8.6c.11.36-.13.74-.5.74H6.15a.5.5 0 0 1-.5-.55l.27-2.6c.02-.26-.27-.37-.41-.16-.48.74-1.03 1.8-1.32 2.9a.53.53 0 0 1-.5.41h-.22C2.66 22 2 21.34 2 20.53Z" /><path fill="currentColor" d="M24 19a5 5 0 1 1-10 0 5 5 0 0 1 10 0Z" /></svg>;

export const ListViewIcon = props => <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path fill="currentColor" d="M4 2a2 2 0 1 0 0 4 2 2 0 0 0 0-4ZM4 10a2 2 0 1 0 0 4 2 2 0 0 0 0-4ZM2 20a2 2 0 1 1 4 0 2 2 0 0 1-4 0ZM9 3a1 1 0 0 0 0 2h12a1 1 0 1 0 0-2H9ZM8 12a1 1 0 0 1 1-1h12a1 1 0 1 1 0 2H9a1 1 0 0 1-1-1ZM9 19a1 1 0 1 0 0 2h12a1 1 0 1 0 0-2H9Z" /></svg>;

## Overview

This guide will walk you through integrating the Discord Social SDK into a Unity project. By the end, you'll have a project that can:

* Authenticate users with Discord
* Set up logging and status monitoring
* Start the SDK and establish a connection
* Request the number of Discord friends the player has
* Set the player's rich presence for your game

### Prerequisites

Before starting, ensure you have:

* Unity 2021.3 or later

Let's walk through the steps in detail.

***

## Step 1: Create a Discord Developer Team

Before you start, you'll need to create a developer team on the Discord Developer Portal. This team will be used to manage your Discord applications and SDK integrations.

If you already have a team configured, you can skip this step.

1. Create a developer team on the [Discord Developer Portal](https://discord.com/developers/teams).

Later, you can invite your team members to your new team to collaborate on your integration.

***

## Step 2: Create a Discord Application

1. Create a new application on the [Discord Developer Portal](https://discord.com/developers/applications) and assign it to your team.
2. Add a redirect URL in the [OAuth2 tab](https://discord.com/developers/applications/select/oauth2):
   * For desktop applications: `http://127.0.0.1/callback` (this can be changed later).
   * See [`discordpp::Client::Authorize`](https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#ace94a58e27545a933d79db32b387a468) for more details on setting up more advanced redirect URIs.
3. Enable the `Public Client` toggle in the [OAuth2 tab](https://discord.com/developers/applications/select/oauth2).

<Warning>
  This guide requires enabling **Public Client** to allow you to get started with the SDK quickly. Most games will not want to ship as a public client. This setting should be reviewed by your team prior to releasing your game. [Learn more about public clients](/developers/discord-social-sdk/core-concepts/oauth2-scopes#oauth2-client-types).
</Warning>

***

## Step 3: Enable Discord Social SDK for Your App

Once you've created your Discord application, you'll need to enable the Discord Social SDK for it.

1. From the [Discord Developer Portal](https://discord.com/developers/applications), select your newly created application from Step 2.
2. In the left sidebar for your app, locate and click the [Getting Started](https://discord.com/developers/applications/select/social-sdk/getting-started) link under `Discord Social SDK`.
3. Fill out the form to share details about your game.
4. Click `Submit` and the Social SDK will be enabled for your application.
5. Once enabled, you'll find binaries for the Social SDK under [Downloads](https://discord.com/developers/applications/select/social-sdk/downloads).

***

## Step 4: Download the Social SDK for Unity

1. Click on the [Downloads](https://discord.com/developers/applications/select/social-sdk/downloads) link under the Discord Social SDK section of the sidebar.
2. Select the latest version from the version dropdown and download the SDK for Unity.

<Info>
  A Unity sample project is available for download on this page, but we are not going to cover it in this guide. Explore it on your own after you finish this guide!
</Info>

***

## Step 5: Project Setup

Let's set up your Unity project to include the Social SDK package and add the necessary objects and scripts to use it.

1. Create a new 2D project in Unity Hub using Unity version 2021.3 or later
2. Either:
   1. Unzip the zip file in the Unity `Packages` folder, or
   2. Unzip the zip file and [Install Package from Disk](https://docs.unity3d.com/Manual/upm-ui-local.html). Make sure the folder is in a directory that won't get moved or deleted as your Unity project will load it from that location.
3. In your project add a `Scripts` folder and create a `DiscordManager.cs` script
4. Add the following code to `DiscordManager.cs`:

```cs theme={null}
using UnityEngine;
using UnityEngine.UI;
using Discord.Sdk;
using System.Linq;

public class DiscordManager : MonoBehaviour
{
    [SerializeField] 
    private ulong clientId; // Set this in the Unity Inspector from the dev portal
    
    [SerializeField]
    private Button loginButton; 
    
    [SerializeField] 
    private Text statusText;

    private Client client;
    private string codeVerifier;
}
```

6. Add an empty object to the scene (**GameObject > Create Empty**) called **DiscordManager** and attach the `DiscordManager.cs` script to it
7. Add a button to the scene **GameObject > UI > Legacy > Button**
8. Add text to the scene **GameObject > UI > Legacy > Text**
9. Position the button and text somewhere visible on the screen
10. Attach the button and text to the **DiscordManager** in the inspector
11. Run it!

This is all we'll need to get started! You shouldn't see anything happen, but if you run into any issues, check out the troubleshooting section before moving to the next step.

### Troubleshooting

* Make sure the Social SDK package was successfully added to Unity

<Accordion title="Mac libdiscord_partner_sdk.dylib Not Opened">
  On Mac you may get the error "libdiscord\_partner\_sdk.dylib" Not Opened because Apple couldn't verify it. If this happens press **Done** on the popup.

  <img src="https://mintcdn.com/discord-platform-username/QOcOWyXoil5ne6It/images/social-sdk/getting-started/partials/error.png?fit=max&auto=format&n=QOcOWyXoil5ne6It&q=85&s=12c540c8feb3a959c0066b682886bd4b" alt="Error" width="542" height="544" data-path="images/social-sdk/getting-started/partials/error.png" />

  You'll need to open your **System Settings > Privacy & Security** and scroll down to the **Security** section. It will tell you "libdiscord\_partner\_sdk.dylib" was blocked to protect your Mac. Press **Open Anyway** and try running again.

  <img src="https://mintcdn.com/discord-platform-username/QOcOWyXoil5ne6It/images/social-sdk/getting-started/partials/security-settings.png?fit=max&auto=format&n=QOcOWyXoil5ne6It&q=85&s=67f5d07c53be89bf96fa1e011eb4d794" alt="Settings" width="958" height="370" data-path="images/social-sdk/getting-started/partials/security-settings.png" />

  Now when you get the pop up you'll have the option to select **Open Anyway** and it will be able to use it successfully.

  <img src="https://mintcdn.com/discord-platform-username/QOcOWyXoil5ne6It/images/social-sdk/getting-started/partials/open-anyway.png?fit=max&auto=format&n=QOcOWyXoil5ne6It&q=85&s=9fb2498a256343f43d3652fd6ba9f0b3" alt="Open" width="544" height="710" data-path="images/social-sdk/getting-started/partials/open-anyway.png" />
</Accordion>

***

## Step 6: Setting Up SDK Event Handling

Let's add some event handlers to monitor what's happening with our Discord connection. We'll set up two important callbacks:

* A logging callback to see what the SDK is doing
* A status callback to know when we can start using Discord features

We'll start by adding the following code to your `DiscordManager.cs`:

```cs theme={null}
void Start()
{
    client = new Client();

    // Modifying LoggingSeverity will show you more or less logging information
    client.AddLogCallback(OnLog, LoggingSeverity.Error);
    client.SetStatusChangedCallback(OnStatusChanged);

    // Make sure the button has a listener
    if (loginButton != null)
    {
        //loginButton.onClick.AddListener(StartOAuthFlow);
    }
    else
    {
        Debug.LogError("Login button reference is missing, connect it in the inspector!");
    }

    // Set initial status text
    if (statusText != null)
    {
        statusText.text = "Ready to login";
    }
    else
    {
        Debug.LogError("Status text reference is missing, connect it in the inspector!");
    }
}

private void OnLog(string message, LoggingSeverity severity)
{
    Debug.Log($"Log: {severity} - {message}");
}

private void OnStatusChanged(Client.Status status, Client.Error error, int errorCode)
{
    Debug.Log($"Status changed: {status}");
    statusText.text = status.ToString();
    if(error != Client.Error.None)
    {
        Debug.LogError($"Error: {error}, code: {errorCode}");
    }
}
```

This will hook up the API status changes to your text in the game. Then we'll need to get your Client ID from the [OAuth2 tab](https://discord.com/developers/applications/select/oauth2) in the developer portal and paste it into the ClientID on the **DiscordManager** in the inspector.

### What These Callbacks Do

* The **logging callback** shows you what's happening behind the scenes and is a powerful tool for debugging
* The **status callback** tells you when you're connected and ready to use Discord features

<Info>
  The Unity plugin handles running the SDK callbacks for you in Unity, no need to use [`RunCallbacks`] like we do in the [C++ guide](/developers/discord-social-sdk/getting-started/using-c++).
</Info>

<Info>
  Most Discord features won't work until the status is `Ready`. The status callback lets you know when you can start using them.
</Info>

To get to a `Ready` state, we need to authenticate with Discord. Let's do that next.

***

## Step 7: Account Linking with Discord

In this step, we'll implement OAuth2 authentication to support account linking with Discord. This process will:

1. Open the Discord app or a browser window for Discord login
2. Get an authorization code
3. Exchange it for an access token
4. Connect to Discord

### Add the Authentication Code

<Info>
  **Choosing your OAuth2 scopes:** This guide uses `Client.GetDefaultPresenceScopes()`, which requests the `openid` and `sdk.social_layer_presence` scopes. These enable core features like account linking, friends list, and rich presence.

  If your game also needs lobbies, voice chat, or direct messaging, use `Client.GetDefaultCommunicationScopes()` instead.
  See the [OAuth2 Scopes guide](/developers/discord-social-sdk/core-concepts/oauth2-scopes) for the full breakdown.
</Info>

To start we'll add this code to your `DiscordManager.cs`:

```cs theme={null}
private void StartOAuthFlow() {
    var authorizationVerifier = client.CreateAuthorizationCodeVerifier();
    codeVerifier = authorizationVerifier.Verifier();

    var args = new AuthorizationArgs();
    args.SetClientId(clientId);
    args.SetScopes(Client.GetDefaultPresenceScopes());
    args.SetCodeChallenge(authorizationVerifier.Challenge());
    client.Authorize(args, OnAuthorizeResult);
}

private void OnAuthorizeResult(ClientResult result, string code, string redirectUri) {
    Debug.Log($"Authorization result: [{result.Error()}] [{code}] [{redirectUri}]");
    if (!result.Successful()) {
        return;
    }
    GetTokenFromCode(code, redirectUri);
}

private void GetTokenFromCode(string code, string redirectUri) {
    client.GetToken(clientId,
                    code,
                    codeVerifier,
                    redirectUri,
                    (result, token, refreshToken, tokenType, expiresIn, scope) => {});
}
```

and then we'll uncomment `loginButton.onClick.AddListener(StartOAuthFlow);` in your `Start()` method

```cs theme={null}
if (loginButton != null)
{
    loginButton.onClick.AddListener(StartOAuthFlow);
}
```

### What's Happening Here?

1. We create a code verifier for OAuth2 PKCE security
2. Set up authorization arguments with your app ID and required scopes
3. Start the auth flow with [`Client::Authorize`], which opens a browser
4. When authorized, we exchange the code for an access token

<Warning>
  Never log or store access tokens insecurely! They should be treated as sensitive credentials.
</Warning>

### Testing It Out

Now, if you press play and click the button, it should start the OAuth flow! You'll be redirected to your browser to log in and authorize the game. There will be some logging to the console, but the status won't change yet.

### Troubleshooting

* Make sure you've uncommented `loginButton.onClick.AddListener(StartOAuthFlow);` if the button doesn't seem to do anything
* Double check your `ClientId` is correct
* Ensure you've added the redirect URL in your Discord Developer Portal
* Check the console for specific error messages

<Accordion title="DiscordManager.cs up to this point" icon="code">
  ```cs theme={null}
  using UnityEngine;
  using UnityEngine.UI;
  using Discord.Sdk;
  using System.Linq;

  public class DiscordManager : MonoBehaviour
  {
      [SerializeField] 
      private ulong clientId; // Set this in the Unity Inspector from the dev portal
      
      [SerializeField]
      private Button loginButton; 
      
      [SerializeField] 
      private Text statusText;

      private Client client;
      private string codeVerifier;

          void Start()
      {
          client = new Client();

          // Modifying LoggingSeverity will show you more or less logging information
          client.AddLogCallback(OnLog, LoggingSeverity.Error);
          client.SetStatusChangedCallback(OnStatusChanged);

          // Make sure the button has a listener
          if (loginButton != null)
          {
              loginButton.onClick.AddListener(StartOAuthFlow);
          }
          else
          {
              Debug.LogError("Login button reference is missing, connect it in the inspector!");
          }

          // Set initial status text
          if (statusText != null)
          {
              statusText.text = "Ready to login";
          }
          else
          {
              Debug.LogError("Status text reference is missing, connect it in the inspector!");
          }
      }

      private void OnLog(string message, LoggingSeverity severity)
      {
          Debug.Log($"Log: {severity} - {message}");
      }

      private void OnStatusChanged(Client.Status status, Client.Error error, int errorCode)
      {
          Debug.Log($"Status changed: {status}");
          statusText.text = status.ToString();
          if(error != Client.Error.None)
          {
              Debug.LogError($"Error: {error}, code: {errorCode}");
          }
      }
      
      private void StartOAuthFlow() {
          var authorizationVerifier = client.CreateAuthorizationCodeVerifier();
          codeVerifier = authorizationVerifier.Verifier();
          
          var args = new AuthorizationArgs();
          args.SetClientId(clientId);
          args.SetScopes(Client.GetDefaultPresenceScopes());
          args.SetCodeChallenge(authorizationVerifier.Challenge());
          client.Authorize(args, OnAuthorizeResult);
      }

      private void OnAuthorizeResult(ClientResult result, string code, string redirectUri) {
          Debug.Log($"Authorization result: [{result.Error()}] [{code}] [{redirectUri}]");
          if (!result.Successful()) {
              return;
          }
          GetTokenFromCode(code, redirectUri);
      }

      private void GetTokenFromCode(string code, string redirectUri) {
          client.GetToken(clientId,
                          code,
                          codeVerifier,
                          redirectUri,
                          (result, token, refreshToken, tokenType, expiresIn, scope) => {});
      }
  }
  ```
</Accordion>

***

## Step 8: Connect the SDK to Discord

Now that we have our access token, let's connect to Discord!

To start, we'll add this code to your `DiscordManager.cs`:

```cs theme={null}
private void OnReceivedToken(string token) {
    Debug.Log("Token received: " + token);
    client.UpdateToken(AuthorizationTokenType.Bearer, token, (ClientResult result) => { client.Connect(); });
}

private void OnRetrieveTokenFailed() { statusText.text = "Failed to retrieve token"; }
```

Then we'll update `GetTokenFromCode` to call these functions when it completes:

```cs theme={null}
private void GetTokenFromCode(string code, string redirectUri) {
    client.GetToken(clientId,
                    code,
                    codeVerifier,
                    redirectUri,
                    (result, token, refreshToken, tokenType, expiresIn, scope) => {
                        if (token != "") {
                            OnReceivedToken(token);
                        } else {
                            OnRetrieveTokenFailed();
                        }
                    });
}
```

### What's Happening Here?

1. [`Client::UpdateToken`] tells the SDK to use our access token for Discord API calls
2. Once the token is updated, we call [`Client::Connect`] in the callback
3. The SDK will begin connecting asynchronously
4. Our status text will tell you when the SDK is ready!

### Testing the Connection

Press play and click the button again to log in and authorize the game. This time you should see the status text change as it goes through the OAuth flow, and it should end up `Ready`

### Troubleshooting

If you don't see `Ready` status:

* Check that your access token is valid
* Ensure you have internet connectivity
* Look for error messages from the SDK in the console
* Verify your `ClientID` set in the inspector is correct

<Accordion title="DiscordManager.cs up to this point" icon="code">
  ```cs theme={null}
  using UnityEngine;
  using UnityEngine.UI;
  using Discord.Sdk;
  using System.Linq;

  public class DiscordManager : MonoBehaviour
  {
      [SerializeField] 
      private ulong clientId; // Set this in the Unity Inspector from the dev portal
      
      [SerializeField]
      private Button loginButton; 
      
      [SerializeField] 
      private Text statusText;

      private Client client;
      private string codeVerifier;

          void Start()
      {
          client = new Client();

          // Modifying LoggingSeverity will show you more or less logging information
          client.AddLogCallback(OnLog, LoggingSeverity.Error);
          client.SetStatusChangedCallback(OnStatusChanged);

          // Make sure the button has a listener
          if (loginButton != null)
          {
              loginButton.onClick.AddListener(StartOAuthFlow);
          }
          else
          {
              Debug.LogError("Login button reference is missing, connect it in the inspector!");
          }

          // Set initial status text
          if (statusText != null)
          {
              statusText.text = "Ready to login";
          }
          else
          {
              Debug.LogError("Status text reference is missing, connect it in the inspector!");
          }
      }

      private void OnLog(string message, LoggingSeverity severity)
      {
          Debug.Log($"Log: {severity} - {message}");
      }

      private void OnStatusChanged(Client.Status status, Client.Error error, int errorCode)
      {
          Debug.Log($"Status changed: {status}");
          statusText.text = status.ToString();
          if(error != Client.Error.None)
          {
              Debug.LogError($"Error: {error}, code: {errorCode}");
          }
      }

      private void StartOAuthFlow() {
          var authorizationVerifier = client.CreateAuthorizationCodeVerifier();
          codeVerifier = authorizationVerifier.Verifier();
          
          var args = new AuthorizationArgs();
          args.SetClientId(clientId);
          args.SetScopes(Client.GetDefaultPresenceScopes());
          args.SetCodeChallenge(authorizationVerifier.Challenge());
          client.Authorize(args, OnAuthorizeResult);
      }

      private void OnAuthorizeResult(ClientResult result, string code, string redirectUri) {
          Debug.Log($"Authorization result: [{result.Error()}] [{code}] [{redirectUri}]");
          if (!result.Successful()) {
              return;
          }
          GetTokenFromCode(code, redirectUri);
      }

      private void GetTokenFromCode(string code, string redirectUri) {
          client.GetToken(clientId,
                          code,
                          codeVerifier,
                          redirectUri,
                          (result, token, refreshToken, tokenType, expiresIn, scope) => {
                              if (token != "") {
                                  OnReceivedToken(token);
                              } else {
                                  OnRetrieveTokenFailed();
                              }
                          });
      }

      private void OnReceivedToken(string token) {
          Debug.Log("Token received: " + token);
          client.UpdateToken(AuthorizationTokenType.Bearer, token, (ClientResult result) => { client.Connect(); });
      }

      private void OnRetrieveTokenFailed() { statusText.text = "Failed to retrieve token"; }
  }
  ```
</Accordion>

Now that your client is in a ready state, we can start implementing Discord social features.

***

## Step 9: Access Discord Relationships

Let's access the user's Discord relationships (friends list) and display the count. This will help you understand how to access and use Discord data in your game.

Lets add some new code to your `DiscordManager.cs`:

```cs theme={null}
private void ClientReady()
{
    Debug.Log($"Friend Count: {client.GetRelationships().Count()}");
}
```

We want to call this when the client is ready to use which we'll know in our `OnStatusChanged` method:

```cs theme={null}
private void OnStatusChanged(Client.Status status, Client.Error error, int errorCode)
{
    Debug.Log($"Status changed: {status}");
    statusText.text = status.ToString();
    if(error != Client.Error.None)
    {
        Debug.LogError($"Error: {error}, code: {errorCode}");
    }

    if (status == Client.Status.Ready)
    {
        ClientReady();
    }
}
```

### What This Code Does

When the client status is `Ready,` it'll call our `ClientReady` function, which will call [`Client::GetRelationships`], returning us a list of all the player's friends. We then log the number of friends directly to the console.

### Testing It Out

Hit play and then click the button. Once the OAuth flow completes and you see the status hit `Ready` check the console to see the output!

### Example Output

```
Friend Count: 42
```

### Troubleshooting

* Verify your OAuth2 scopes include relationships access
* Ensure you're connected (status is `Ready`)
* Check that you have friends on Discord
* Look for errors in the logging callback

Next, we'll learn how to show your game's activity on Discord with Rich Presence!

<Accordion title="DiscordManager.cs up to this point" icon="code">
  ```cs theme={null}
  using UnityEngine;
  using UnityEngine.UI;
  using Discord.Sdk;
  using System.Linq;

  public class DiscordManager : MonoBehaviour
  {
      [SerializeField] 
      private ulong clientId; // Set this in the Unity Inspector from the dev portal
      
      [SerializeField]
      private Button loginButton; 
      
      [SerializeField] 
      private Text statusText;

      private Client client;
      private string codeVerifier;

          void Start()
      {
          client = new Client();

          // Modifying LoggingSeverity will show you more or less logging information
          client.AddLogCallback(OnLog, LoggingSeverity.Error);
          client.SetStatusChangedCallback(OnStatusChanged);

          // Make sure the button has a listener
          if (loginButton != null)
          {
              loginButton.onClick.AddListener(StartOAuthFlow);
          }
          else
          {
              Debug.LogError("Login button reference is missing, connect it in the inspector!");
          }

          // Set initial status text
          if (statusText != null)
          {
              statusText.text = "Ready to login";
          }
          else
          {
              Debug.LogError("Status text reference is missing, connect it in the inspector!");
          }
      }

      private void OnLog(string message, LoggingSeverity severity)
      {
          Debug.Log($"Log: {severity} - {message}");
      }

      private void OnStatusChanged(Client.Status status, Client.Error error, int errorCode)
      {
          Debug.Log($"Status changed: {status}");
          statusText.text = status.ToString();
          if(error != Client.Error.None)
          {
              Debug.LogError($"Error: {error}, code: {errorCode}");
          }

          if (status == Client.Status.Ready)
          {
              ClientReady();
          }
      }

      private void ClientReady()
      {
          Debug.Log($"Friend Count: {client.GetRelationships().Count()}");
      }


      private void StartOAuthFlow() {
          var authorizationVerifier = client.CreateAuthorizationCodeVerifier();
          codeVerifier = authorizationVerifier.Verifier();
          
          var args = new AuthorizationArgs();
          args.SetClientId(clientId);
          args.SetScopes(Client.GetDefaultPresenceScopes());
          args.SetCodeChallenge(authorizationVerifier.Challenge());
          client.Authorize(args, OnAuthorizeResult);
      }

      private void OnAuthorizeResult(ClientResult result, string code, string redirectUri) {
          Debug.Log($"Authorization result: [{result.Error()}] [{code}] [{redirectUri}]");
          if (!result.Successful()) {
              return;
          }
          GetTokenFromCode(code, redirectUri);
      }

      private void GetTokenFromCode(string code, string redirectUri) {
          client.GetToken(clientId,
                          code,
                          codeVerifier,
                          redirectUri,
                          (result, token, refreshToken, tokenType, expiresIn, scope) => {
                              if (token != "") {
                                  OnReceivedToken(token);
                              } else {
                                  OnRetrieveTokenFailed();
                              }
                          });
      }

      private void OnReceivedToken(string token) {
          Debug.Log("Token received: " + token);
          client.UpdateToken(AuthorizationTokenType.Bearer, token, (ClientResult result) => { client.Connect(); });
      }

      private void OnRetrieveTokenFailed() { statusText.text = "Failed to retrieve token"; }
  }
  ```
</Accordion>

***

## Step 10: Set Rich Presence

Let's show your game's activity on Discord using Rich Presence. This feature lets players see what others are doing in your game directly in their Discord friends list.

Update your `ClientReady` method with this code:

```cs theme={null}
private void ClientReady()
{
    Debug.Log($"Friend Count: {client.GetRelationships().Count()}");

    Activity activity = new Activity();
    activity.SetType(ActivityTypes.Playing);
    activity.SetState("In Competitive Match");
    activity.SetDetails("Rank: Diamond II");
    client.UpdateRichPresence(activity, (ClientResult result) => {
        if (result.Successful()) {
            Debug.Log("Rich presence updated!");
        } else {
            Debug.LogError("Failed to update rich presence");
        }
    });
}
```

### What This Code Does

1. Creates an [`Activity`] object to represent what the player is doing
2. Sets basic information like:

* The activity type (Playing)
* Current state ("In Competitive Match")
* Additional details ("Rank: Diamond II")

3. Updates your rich presence on Discord

### Testing It Out

Hit play and then click the button. Once the OAuth flow is complete, you will see the status hit `Ready`. The console will tell you if setting rich presence was successful, and you can check your Discord profile to see it!

### Troubleshooting

If you don't see your presence:

* Ensure you're connected (status is `Ready`)
* Check the console for error messages
* Verify your activity settings are valid
* Make sure you're not invisible on Discord

***

<Accordion title="The full DiscordManager.cs" icon="code">
  ```cs theme={null}
  using UnityEngine;
  using UnityEngine.UI;
  using Discord.Sdk;
  using System.Linq;

  public class DiscordManager : MonoBehaviour
  {
      [SerializeField] 
      private ulong clientId; // Set this in the Unity Inspector from the dev portal
      
      [SerializeField]
      private Button loginButton; 
      
      [SerializeField] 
      private Text statusText;

      private Client client;
      private string codeVerifier;

          void Start()
      {
          client = new Client();

          // Modifying LoggingSeverity will show you more or less logging information
          client.AddLogCallback(OnLog, LoggingSeverity.Error);
          client.SetStatusChangedCallback(OnStatusChanged);

          // Make sure the button has a listener
          if (loginButton != null)
          {
              loginButton.onClick.AddListener(StartOAuthFlow);
          }
          else
          {
              Debug.LogError("Login button reference is missing, connect it in the inspector!");
          }

          // Set initial status text
          if (statusText != null)
          {
              statusText.text = "Ready to login";
          }
          else
          {
              Debug.LogError("Status text reference is missing, connect it in the inspector!");
          }
      }

      private void OnLog(string message, LoggingSeverity severity)
      {
          Debug.Log($"Log: {severity} - {message}");
      }

      private void OnStatusChanged(Client.Status status, Client.Error error, int errorCode)
      {
          Debug.Log($"Status changed: {status}");
          statusText.text = status.ToString();
          if(error != Client.Error.None)
          {
              Debug.LogError($"Error: {error}, code: {errorCode}");
          }

          if (status == Client.Status.Ready)
          {
              ClientReady();
          }
      }

      private void ClientReady()
      {
              Debug.Log($"Friend Count: {client.GetRelationships().Count()}");

              Activity activity = new Activity();
              activity.SetType(ActivityTypes.Playing);
              activity.SetState("In Competitive Match");
              activity.SetDetails("Rank: Diamond II");
              client.UpdateRichPresence(activity, (ClientResult result) => {
                  if (result.Successful()) {
                      Debug.Log("Rich presence updated!");
                  } else {
                      Debug.LogError("Failed to update rich presence");
                  }
              });
      }

      private void StartOAuthFlow() {
          var authorizationVerifier = client.CreateAuthorizationCodeVerifier();
          codeVerifier = authorizationVerifier.Verifier();
          
          var args = new AuthorizationArgs();
          args.SetClientId(clientId);
          args.SetScopes(Client.GetDefaultPresenceScopes());
          args.SetCodeChallenge(authorizationVerifier.Challenge());
          client.Authorize(args, OnAuthorizeResult);
      }

      private void OnAuthorizeResult(ClientResult result, string code, string redirectUri) {
          Debug.Log($"Authorization result: [{result.Error()}] [{code}] [{redirectUri}]");
          if (!result.Successful()) {
              return;
          }
          GetTokenFromCode(code, redirectUri);
      }

      private void GetTokenFromCode(string code, string redirectUri) {
          client.GetToken(clientId,
                          code,
                          codeVerifier,
                          redirectUri,
                          (result, token, refreshToken, tokenType, expiresIn, scope) => {
                              if (token != "") {
                                  OnReceivedToken(token);
                              } else {
                                  OnRetrieveTokenFailed();
                              }
                          });
      }

      private void OnReceivedToken(string token) {
          Debug.Log("Token received: " + token);
          client.UpdateToken(AuthorizationTokenType.Bearer, token, (ClientResult result) => { client.Connect(); });
      }

      private void OnRetrieveTokenFailed() { statusText.text = "Failed to retrieve token"; }
  }
  ```
</Accordion>

***

## Conclusion

Congratulations! You've successfully integrated the Discord Social SDK into Unity. Let's review what you've accomplished:

### What You've Built

* ✅ Created a Discord application and configured OAuth2
* ✅ Set up SDK logging and status monitoring
* ✅ Implemented user authentication flow
* ✅ Retrieved Discord relationships data
* ✅ Added Rich Presence support

### Key Concepts Learned

* How to initialize and configure the Discord SDK
* Managing authentication and connections
* Working with Discord's social features
* Handling asynchronous callbacks
* Monitoring SDK status and events

***

## Next Steps

### Social SDK Unity sample

Check out our [in depth sample for using the Social SDK in Unity](https://github.com/discord/social-sdk-unity-sample) following the best practices laid out in these guides. It contains easy to drop in prefabs with both code and UI to quickly integrate Discord's social features into your game.

<img src="https://mintcdn.com/discord-platform-username/QOcOWyXoil5ne6It/images/social-sdk/getting-started/unity-sample-preview.webp?fit=max&auto=format&n=QOcOWyXoil5ne6It&q=85&s=2828b21319bf8fe1ffa0107e975d474c" alt="Video showing off the Unity sample with the Discord Social SDK" width="800" height="531" data-path="images/social-sdk/getting-started/unity-sample-preview.webp" />

<CardGroup cols={3}>
  <Card title="Creating a Unified Friends List" href="/developers/discord-social-sdk/development-guides/creating-a-unified-friends-list" icon={<ListViewIcon />}>
    Create a unified friends list combining Discord and game-specific friendships
  </Card>

  <Card title="Setting Rich Presence" href="/developers/discord-social-sdk/development-guides/setting-rich-presence" icon={<UserStatusIcon />}>
    Customize your game's rich presence to show more advanced information and game invites
  </Card>

  <Card title="Managing Game Invites" href="/developers/discord-social-sdk/development-guides/managing-game-invites" icon={<InboxIcon />}>
    Allow players to invite friends to join their game session or party.
  </Card>
</CardGroup>

Need help? Join the [Discord Developers Server](https://discord.gg/discord-developers) and share questions in the `#social-sdk-dev-help` channel for support from the community.

If you encounter a bug while working with the Social SDK, please report it here:  [https://dis.gd/social-sdk-bug-report](https://dis.gd/social-sdk-bug-report)

***

## Change Log

| Date           | Changes         |
| -------------- | --------------- |
| March 17, 2025 | Initial release |

[`Activity`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Activity.html#ae793d9adbe16fef402b859ba02bee682

[`Client::Authorize`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#ace94a58e27545a933d79db32b387a468

[`Client::Connect`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a873a844c7c4c72e9e693419bb3e290aa

[`Client::GetRelationships`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#ad481849835cd570f0e03adafcf90125d

[`Client::UpdateToken`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a606b32cef7796f7fb91c2497bc31afc4

[`RunCallbacks`]: https://discord.com/developers/docs/social-sdk/namespacediscordpp.html#ab5dd8cf274f581ee1885de5816be3c29
