Skip to main content
  • Unity 6000.0+ (Unity 6) or newer
  • Environment ID from Dynamic Dashboard
  • macOS, iOS, or Android for testing (Windows/Linux editors support development only)
Passkey Limitation: If an account is secured with a Passkey, it cannot be used in the Unity Editor for testing. Passkey authentication requires a native device (iOS/Android). All other authentication methods work in the Editor on macOS.

Install the SDK

Step 1: Add scoped registry

Open your Unity project and go to Edit > Project Settings > Package Manager. Add a new scoped registry:
FieldValue
NameDynamic SDK
URLhttps://packages.dynamic.xyz
Scope(s)xyz.dynamic.unitysdk

Step 2: Install the SDK

Open Window > Package Manager, click the + button, and select Install package by name. Enter: xyz.dynamic.unitysdk Leave the version blank to install the latest version.

Step 3: Install UniTask (required dependency)

Open Packages/manifest.json in a text editor and add to the dependencies section:
"com.cysharp.unitask": "https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask"

Step 4: Install Solana support (optional)

If you need Solana transaction building (not just message signing), install the Solana extension package. In Package Manager > Install package by name, enter: xyz.dynamic.unitysdk.solana Then add the following to your Packages/manifest.json dependencies:
"com.solana.unity_sdk": "https://github.com/kantagara/Solana.Unity-SDK.git"
The Solana extension package only enables transaction building (RPC calls, PublicKey, SystemProgram.Transfer, etc.). Plain-text message signing via the Dynamic webview works without this package.

Android setup

Required for Android builds: You must configure the Main Gradle Template for Android builds to work properly.
Go to Edit > Project Settings > Player > Android > Publishing Settings and enable:
  • Custom Main Gradle Template
This creates Assets/Plugins/Android/mainTemplate.gradle. Replace its contents with:
apply plugin: 'com.android.library'
apply from: '../shared/keepUnitySymbols.gradle'
**APPLY_PLUGINS**

dependencies {
    implementation 'androidx.browser:browser:1.8.0'
    implementation 'androidx.core:core:1.13.1'
    implementation 'androidx.versionedparcelable:versionedparcelable:1.2.1'
    implementation 'com.google.guava:guava:33.5.0-android'
    implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'
    
    implementation "androidx.credentials:credentials:1.3.0"
    implementation "androidx.credentials:credentials-play-services-auth:1.3.0"
    implementation "androidx.concurrent:concurrent-futures:1.2.0"
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.datastore:datastore-preferences:1.1.1'
    implementation 'com.google.crypto.tink:tink-android:1.11.0'
**DEPS**}

android {
    namespace "com.unity3d.player"
    ndkPath "**NDKPATH**"
    ndkVersion "**NDKVERSION**"
    compileSdk **APIVERSION**
    buildToolsVersion = "**BUILDTOOLS**"
    
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_17
        targetCompatibility JavaVersion.VERSION_17
    }
    
    defaultConfig {
        minSdk **MINSDK**
        targetSdk **TARGETSDK**
        ndk {
            abiFilters **ABIFILTERS**
            debugSymbolLevel **DEBUGSYMBOLLEVEL**
        }
        versionCode **VERSIONCODE**
        versionName '**VERSIONNAME**'
        consumerProguardFiles 'proguard-unity.txt'**USER_PROGUARD**
**DEFAULT_CONFIG_SETUP**
    }
    
    lint {
        abortOnError false
    }
    
    androidResources {
        noCompress = **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ')
        ignoreAssetsPattern = "!.svn:!.git:!.ds_store:!*.scc:!CVS:!thumbs.db:!picasa.ini:!*~"
    }**PACKAGING**
}

**IL_CPP_BUILD_SETUP**
**SOURCE_BUILD_SETUP**
**EXTERNAL_SOURCES**

configurations.all {
    exclude group: 'com.google.guava', module: 'listenablefuture'
    exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7'
    exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk8'
    resolutionStrategy {
        force 'androidx.core:core:1.13.1'
    }
}
Key dependencies explained:
  • androidx.credentials + credentials-play-services-auth — required for Passkey (WebAuthn) support
  • androidx.datastore + tink-android — required for secure storage
  • androidx.browser — required for OAuth social login flows
  • com.google.guava — required by Solana SDK

Initialize the SDK

Step 1: Create configuration asset

In the Unity Editor: Assets > Create > DynamicSDK > Client Props This creates a ClientPropsData ScriptableObject. Configure it in the Inspector:
FieldRequiredDescription
Environment IDYesYour environment ID from the Dynamic dashboard
App NameNoYour application name
App Logo URLNoURL to your app logo
App OriginYesMandatory for EOA connections and for passkey verification
Log LevelNoError (default), Warning, Info, or Debug
Debug WebviewNoEnable WebView debugging

Step 2: Create initializer script

Create a MonoBehaviour that initializes the SDK on Awake:
using DynamicSDK.Core;
using UnityEngine;

public class DynamicSDKManager : MonoBehaviour
{
    [SerializeField] private ClientPropsData props;
    
    private void Awake()
    {
        DynamicSDK.DynamicSDK.Init(props);
    }
}
Attach this script to a GameObject in your scene and assign the ClientPropsData asset to the props field. The SDK creates a DontDestroyOnLoad GameObject and persists across scene loads.

Step 3: Wait for SDK ready

Important: Do not call any SDK methods (auth, wallets, signing, etc.) before IsWebViewReady is true or the OnWebViewReady event fires.
The SDK loads asynchronously via WebView. You must wait for it to be ready:
void Start()
{
    if (DynamicSDK.DynamicSDK.Instance.IsWebViewReady)
    {
        OnSdkReady();
    }
    else
    {
        DynamicSDK.DynamicSDK.Instance.OnWebViewReady += OnSdkReady;
    }
}

private void OnSdkReady()
{
    Debug.Log("Dynamic SDK is ready!");
    
    // Subscribe to auth state changes
    DynamicSDK.DynamicSDK.Instance.Auth.OnTokenChanged += OnTokenChanged;
    DynamicSDK.DynamicSDK.Instance.Auth.OnUserChanged += OnUserChanged;
}

private void OnTokenChanged(string token)
{
    if (string.IsNullOrEmpty(token))
    {
        Debug.Log("User logged out");
        // Navigate to login screen, clear UI, etc.
    }
    else
    {
        Debug.Log("User authenticated!");
        // Navigate to main screen, load wallets, etc.
    }
}

private void OnUserChanged(UserProfile user)
{
    if (user != null)
        Debug.Log($"User: {user.Email}");
}

Basic usage

Using built-in authentication UI

The easiest way to add authentication is using the Dynamic Widget:
// Show authentication UI
DynamicSDK.Instance.UI.ShowAuth();

Listening for authentication state

// Get current auth token
string token = DynamicSDK.Instance.Auth.Token;

// Subscribe to auth state changes
DynamicSDK.Instance.Auth.OnTokenChanged += (token) =>
{
    if (!string.IsNullOrEmpty(token))
        Debug.Log("User logged in");
    else
        Debug.Log("User logged out");
};

// Get current user profile
DynamicSDK.Instance.Auth.OnUserChanged += (user) =>
{
    if (user != null)
        Debug.Log($"User: {user.Email}");
};

// Logout
await DynamicSDK.Instance.Auth.Logout();

Enable features in dashboard

Before you can use authentication and wallet features, enable them in your Dynamic dashboard:
  1. Go to your Dynamic Dashboard
  2. Select your project
  3. Go to Authentication and enable the methods you want to use:
    • Email OTP
    • SMS OTP
    • Social providers (Google, Apple, Farcaster)
    • Passkeys
  4. Go to Wallets and enable embedded wallets
  5. Go to Chains and enable the networks you want to support (EVM, Solana, and/or SUI)
For testing, we recommend starting with Email OTP authentication and an EVM testnet like Base Sepolia. This gives you a complete setup without requiring real phone numbers or mainnet transactions.

Troubleshooting

Common issues

  • SDK not initialized
    • Ensure DynamicSDK.Init(props) is called in Awake() before any other SDK methods
    • Wait for OnWebViewReady event before calling SDK methods
  • Passkeys not working in Editor
    • Passkey authentication only works on native devices (iOS/Android)
    • Use Email OTP or Social login for Editor testing on macOS
  • Android build fails
    • Verify the Main Gradle Template is configured correctly
    • Check that all required dependencies are included
  • WebView not loading
    • Check your Environment ID is correct
    • Ensure App Origin is set for passkey and EOA connections
    • Enable Debug Webview to see console logs

What’s next

  1. Introduction - Learn about all SDK features and architecture
  2. Authentication Guide - Implement email, SMS, social, and passkey authentication
  3. Session Management - Manage authenticated sessions
  4. Wallet Operations - Work with balances and transactions
  5. EVM Operations - Send EVM transactions
  6. Solana Operations - Send Solana transactions
  7. SUI Operations - Send SUI transactions