Unity SDK
The Immutable SDK for Unity helps you integrate your game with Immutable Passport.
- Windows (64-bit) - Supports Mono builds only, not IL2CPP
- macOS (minimum version 12.5)
- Android (minimum version 5.1)
- iOS (minimum version 15.2)
- Unity 2021.3 or newer for Windows, macOS, Android and iOS
- Unity 2019.4 or newer for macOS, Android, and iOS. Windows isn't supported on Unity versions from 2019.4 up through 2021.2.
We have added compilation flags to our Unity SDK to ensure that specific Unity editors can only build certain platform targets. Please note that the table below indicates which editor you can use to build a platform target, but it does not determine whether you can run the SDK in that editor.
For example, our SDK allows you to build iOS games using a macOS Unity Editor, but you cannot use the Windows Unity Editor.
- Target Platform: The platform you're building for
- Unity Editor Platform: The OS you're running the Unity Editor on
Target Platform | Windows | macOS | Android | iOS |
---|---|---|---|---|
Windows Unity Editor | ✅ | ❌ | ✅ | ❌ |
macOS Unity Editor | ❌ | ✅ | ✅ | ✅ |
Registering your game
Before using Passport, you must register your application as an OAuth 2.0 Native client in the Immutable Hub.
First, you'll need to create a project and a testnet environment. Then, you can navigate to the Passport config screen and create a passport client for your created environment. When you're ready to launch your application on the mainnet, please ensure you configure a passport client under a mainnet environment.
Here's how you can configure the fields while creating a client:
Creating an OAuth2.0 Native client
Application Type
This field is required.
You must register your application as an OAuth 2.0 Native client.
Client name
This field is required.
The name you wish to use to identify your application.
Redirect URLs
This field is required.
If you wish to use PKCE login on Android, iOS and macOS clients, you must set your application's deep link (e.g. mygame://callback
). Otherwise, set it to your website or https://localhost:3000.
Windows clients do not support PKCE login, so they do not use Redirect URLs.
Logout URLs
This field is required.
If you wish to use PKCE login on Android, iOS and macOS clients, you must set your application's logout deep link (e.g. mygame://logout
). The deep link for Logout URLs must differ from Redirect URLs. Otherwise, use your website, https://localhost:3000 or set it to be the same as Redirect URLs.
Windows clients do not support PKCE login, so Logout URLs are unused.
Web Origins URLs
The Unity SDK doesn't utilise this field. You may leave it blank.
See here for more details.
Installation
Install by cloning the repository
- Since
.dll
files are stored on Git Large File Storage, you must download and install git-lfs from here before cloning the repository - Clone the unity-immutable-sdk repository or download the zip/tarball from one of the versions here
- Open the Package Manager
- Click the add + button and select "Add package from disk..."
- Navigate to the Passport package root folder (
src/Packages/Passport
) - Double-click the
package.json
file
Install from a zip file
- Go to our Unity SDK GitHub Releases
- Click on the version you would like to install
- Download the
Immutable-Passport.zip
and extract the zip file - Open the Package Manager
- Click the add + button and select "Add package from disk..."
- Navigate to the Passport package root folder (
src/Packages/Passport
) - Double-click the
package.json
file
Install from a Git URL
Via UPM window
- Since
.dll
files are stored on Git Large File Storage, you must download and install git-lfs from here - Open the Package Manager
- Click the add + button and select "Add package from git URL..."
- Enter
https://github.com/immutable/unity-immutable-sdk.git?path=/src/Packages/Passport
and click 'Add'
Via manifest.json
- Since
.dll
files are stored on Git Large File Storage, you must download and install git-lfs from here - Open your project's
Packages/manifest.json
file - Add
"com.immutable.passport": "https://github.com/immutable/unity-immutable-sdk.git?path=/src/Packages/Passport"
in thedependencies
block
Install a specific version
To install a specific version of the SDK from a git URL, append '#' followed by the version tag. For example, https://github.com/immutable/unity-immutable-sdk.git?path=/src/Packages/Passport#v1.0.0
will add the Unity SDK version 1.0.0.
Dependencies
The Unity SDK requires UniTask package (version 2.3.3) as specified in package.json
.
How to install UniTask
Follow the instructions here.
If you encounter any conflicts, please check out Unity's guide here.
Quick Start
Initialise Passport
Create a script with the following code and bind it to an object:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Immutable.Passport;
public class InitPassport : MonoBehaviour
{
private Passport passport;
async void Start()
{
string clientId = "YOUR_IMMUTABLE_CLIENT_ID";
string environment = Immutable.Passport.Model.Environment.SANDBOX; // or PRODUCTION
passport = await Passport.Init(clientId, environment);
}
}
Passport is now accessible from anywhere via Passport.Instance
.
Log into Passport
ZkEvmRequestAccounts
is called.We use the Device Code Authorisation flow to authenticate and authorise gamers.
To log the gamer into Passport:
await passport.Login();
This will open the gamer's default browser and take them through the auth flow.
Initialise the provider and wallet
In order to interact with Immutable zkEVM, you will need to instantiate the Passport's zkEVM provider:
await passport.ConnectEvm();
and then call
await passport.ZkEvmRequestAccounts();
to initialise the gamer's wallet and retrieve their wallet address.
ZkEvmRequestAccounts
is a resource-intensive function. To ensure optimal gaming experience and performance, it is recommended to call this function separately or asynchronously from the login process.
For example, call Login
to log users into the game and let them start playing:
- In the background, call
ConnectEvm
andZkEvmRequestAccounts
functions to initialise their wallet and get their address. - Or later, when users need to use their wallet, call
ConnectEvm
andZkEvmRequestAccounts
functions to initialise their wallet and get their address.
Stored Credentials
Once the gamer is connected to Passport, the SDK will store your credentials (access, ID, and refresh tokens).
You may use Login(useCachedSession: true)
to
re-login the gamer to Passport using the saved credentials. However, if this
fails, it will not fall back to the
Device Code Authorisation
flow.
bool hasCredsSaved = await passport.HasCredentialsSaved();
if (hasCredsSaved)
{
await passport.Login(useCachedSession: true);
// Successfully re-logged into Passport
}
Log out of Passport
To fully log out of Passport, you must clear sessions from both the SDK (local) and the browser used to log in. This requires the SDK to open a browser to clear the browser session when logging out.
To perform a full/hard logout, call:
await passport.Logout(/* hardLogout: true */);
There are two ways to log out from the SDK:
Hard Logout (default): This option clears sessions from both the SDK (local) and the browser used for login. During the logout process, a browser is opened to clear the browser session.
Once the browser session is cleared, the browser redirects to the
logoutRedirectUri
that was configured during Passport initialisation. If nologoutRedirectUri
is specified, the SDK will default to using the logout redirect URI configured in the Immutable Hub client settings.Soft Logout: This option clears only the SDK's local session without affecting the browser session. No browser is opened during the process. To use soft logout, set the
hardLogout
parameter tofalse
. However, keep in mind that with this option, gamers will remain logged in to Passport in the browser until their session expires.
Android, iOS and macOS PKCE login and logout
ZkEvmRequestAccounts
is called.For Android, iOS and macOS you can use the PKCE login flow instead of Device Code. This means the gamer has one less step to complete and will be redirected back to the game after successfully authenticating.
To use this flow you will need to:
- Define a deep link scheme for your game (e.g.
mygame://callback
for logging in andmygame://logout
for logging out) - Login to the Immutable Hub and add the deep links to your clients Redirect URLs and Logout URLs
- Set this deep links as your redirect URI and logout redirect URI in the Passport Init:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Immutable.Passport;
public class InitPassport : MonoBehaviour
{
private Passport passport;
async void Start()
{
string clientId = "YOUR_IMMUTABLE_CLIENT_ID";
string environment = Immutable.Passport.Model.Environment.SANDBOX;
string redirectUri = "mygame://callback";
string logoutRedirectUri = "mygame://logout";
passport = await Passport.Init(clientId, environment, redirectUri, logoutRedirectUri);
}
}
- To:
- Follow the Android, iOS and macOS setup below
Login(useCachedSession: true)
. See Stored Credentials for more details.Android setup
On Android, we utilise Chrome Custom Tabs (if available) to seamlessly connect gamers to Passport from within the game.
For example, on Unity 2019.4, you must upgrade from 3.4.* to 3.4.3 (see Android's blog post):
- In Unity go to Build Settings -> Player Settings -> Android -> Publishing Settings -> Enable Custom Base Gradle Template under the Build section
- Open the newly generated
Assets/Plugins/Android/baseProjectTemplate.grade
file - Update
classpath 'com.android.tools.build:gradle:3.4.0'
toclasspath 'com.android.tools.build:gradle:3.4.3'
- In Unity go to Build Settings -> Player Settings -> Android -> Publishing Settings -> Enable Custom Main Manifest and Custom Main Gradle Template under the Build section
- Open the newly generated
Assets/Plugins/Android/AndroidManifest.xml
file. Add the following code inside the<application>
element:
<activity
android:name="com.immutable.unity.RedirectActivity"
android:exported="true" >
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="mygame" android:host="callback" />
<data android:scheme="mygame" android:host="logout" />
</intent-filter>
</activity>
- Open the newly generated
Assets/Plugins/Android/mainTemplate.gradle
file. Add the following code insidedependencies
block:
compileSdkVersion
must be at least 33. This is usually the same value as the targetSdkVersion
, which you can set in Build Settings -> Player Settings -> Android -> Other Settings -> Target API Level.implementation('androidx.browser:browser:1.5.0')
The application will now open when the device processes any link that starts with mygame://callback
or mygame://logout
.
See the sample app AndroidManifest.xml and mainTemplate.gradle for examples.
Proguard
If you enable Minify in your project settings, you will need to add a custom Proguard file to your project.
- In Unity go to Build Settings -> Player Settings -> Android -> Publishing Settings -> Enable Custom Proguard File under the Build section
- Open the newly generated
Assets/Plugins/Android/proguard-user.txt
file. Add the following code inside the<application>
element
-dontwarn com.immutable.**
-keep class com.immutable.** { *; }
-keep interface com.immutable.** { *; }
-dontwarn androidx.**
-keep class androidx.** { *; }
-keep interface androidx.** { *; }
See the sample app proguard-user.txt for an example.
iOS setup
- In Unity go to Build Settings -> Player Settings -> iOS -> Other Settings -> Supported URL schemes
- Increment the Size number
- Add your URL scheme in the Element field, e.g. if the deeplink URL is
mygame://callback
, add the schememygame
to the field.
macOS setup
No additional setup is required.
zkEVM Send Transaction
Games can only use ERC-20 tokens issued by the game itself, meaning currencies like ETH, USDC, IMX, USDT, etc. cannot be used in-game.
- The zkEVM send transaction feature requires pre-approval from Immutable. Please contact us before making use of it.
to
: The destination addressvalue
: The value to transfer for the transaction in weidata
: Byte string containing the associated data of the message
This method does not support the gas
, gasPrice
, maxPriorityFeePerGas
, or maxFeePerGas
properties as the relayer abstracts these away from the user.
Additionally, the from
property is not supported as the user's Passport wallet address is used instead.
- (Recommended) With Confirmation
- Without Confirmation
Sends a transaction to the network, signs it using the logged-in Passport account, and waits for the transaction to be included in a block.
using Immutable.Passport.Model;
TransactionRequest request = new TransactionRequest()
{
to = address,
value = amount,
data = data
}
TransactionReceiptResponse response = await passport.ZkEvmSendTransactionWithConfirmation(request);
switch (response.status)
{
case "1":
// Successful
break;
case "0":
// Failed
break;
}
Sends a transaction to the network and signs it using the logged-in Passport account.
using Immutable.Passport.Model;
TransactionRequest request = new TransactionRequest()
{
to = address,
value = amount,
data = data
}
string transactionHash = await passport.ZkEvmSendTransaction(request);
ZkEvmGetTransactionReceipt
along with the transaction hash received.As an example:
using System.Threading;
using Cysharp.Threading.Tasks;
async void GetTransactionReceiptStatus()
{
string? status = await PollStatus(
passport,
transactionHash,
TimeSpan.FromSeconds(1), // Poll every one second
TimeSpan.FromSeconds(10) // Stop polling after 10 seconds
);
switch (status)
{
case "0x1":
// Successful
break;
case "0x0":
// Failed
break;
}
}
static async UniTask<string?> PollStatus(Passport passport, string transactionHash, TimeSpan pollInterval, TimeSpan timeout)
{
var cancellationTokenSource = new CancellationTokenSource(timeout);
try
{
while (!cancellationTokenSource.Token.IsCancellationRequested)
{
TransactionReceiptResponse response = await passport.ZkEvmGetTransactionReceipt(transactionHash);
if (response.status == null)
{
// The transaction is still being processed, poll for status again
await UniTask.Delay(delayTimeSpan: pollInterval, cancellationToken: cancellationTokenSource.Token);
}
else
{
return response.status;
}
}
}
catch (OperationCanceledException)
{
// Task was canceled due to timeout
}
return null; // Timeout or could not get transaction receipt
}
See here for more details.
Supported Functionality
Method | Description |
---|---|
Login | Logs into Passport using Device Code Authorisation. If useCachedSession is true, stored credentials will be used to re-login the gamer. If re-login fails, it will not fall back to Device Code Authorisation. |
LoginPKCE | (Android, iOS and macOS only) Logs into Passport using Authorization Code Flow with Proof Key for Code Exchange (PKCE) |
CheckStoredCredentials | Checks if there are stored credits from the previous login |
GetAccessToken | Gets the gamer's access token |
GetIDToken | Gets the gamer's ID token |
Logout | Logs the gamer out of Passport and removes any stored credentials. It is recommended to be used alongside Login to keep the gamer experience consistent. |
LogoutPKCE | Logs the gamer out of Passport and removes any stored credentials. It is recommended to be used alongside LoginPKCE to keep the gamer experience consistent. |
GetLinkedAddresses | Gets the list of external wallets the user has linked to their Passport account via the Dashboard. |
GetEmail | Gets the gamer's email address |
GetPassportId | Gets the gamer's Passport ID |
ConnectEvm | Instantiates the zkEVM provider |
ZkEvmRequestAccounts | Initialises the gamer's Passport wallet and retrieves their wallet address |
ZkEvmGetBalance | Gets the balance of the given address in wei |
ZkEvmSendTransaction | Sends a transaction to the network and signs it using the logged-in Passport account. |
ZkEvmSendTransactionWithConfirmation | Similar to ZkEvmSendTransaction .Sends a transaction to the network, signs it using the logged-in Passport account, and waits for the transaction to be included in a block. |
ZkEvmGetTransactionReceipt | Retrieves the transaction information of a given transaction hash. This function uses the Ethereum JSON-RPC eth_getTransactionReceipt method. |
Examples
- Sample App - see the sample application for examples of how to use the Immutable Unity SDK.
- Sample Game - see the sample game tutorial on how to use the Immutable Unity SDK.
Further documentation
- See the Developer homepage for general information on building on Immutable.
- Build on Immutable zkEVM:
- Build on Immutable X: