Integrate Ethereum into Unity games using Nethereum with async Web3 API, WebGL wallet support via EIP-6963 multi-wallet discovery and MetaMask (.NET/C#). Use this skill when the user asks about Unity blockchain integration, Unity WebGL wallets, Unity MetaMask, Unity Ethereum, Nethereum.Unity, game blockchain, NFT games, or Unity ERC-20 tokens.
Integrate Ethereum into Unity games. Nethereum provides Unity-compatible libraries with the async Web3 API (preferred) and coroutine wrappers, WebGL wallet connectivity (EIP-6963 multi-wallet, MetaMask), and typed contract services.
Add to Packages/manifest.json:
{
"scopedRegistries": [
{
"name": "package.openupm.com",
"url": "https://package.openupm.com",
"scopes": ["com.nethereum.unity"]
}
],
"dependencies": {
"com.nethereum.unity": "5.0.0",
"com.unity.nuget.newtonsoft-json": "3.2.1"
}
}
Important notes:
using UnityEngine;
using Nethereum.Web3;
using Nethereum.Unity.Rpc;
using System;
public class GetBlockNumber : MonoBehaviour
{
public string Url = "https://ethereum-rpc.publicnode.com";
async void Start()
{
var web3 = new Web3(new UnityWebRequestRpcTaskClient(new Uri(Url)));
var blockNumber = await web3.Eth.Blocks.GetBlockNumber.SendRequestAsync();
Debug.Log($"Block: {blockNumber.Value}");
}
}
UnityWebRequestRpcTaskClient uses Unity's UnityWebRequest for HTTP — required for WebGL builds.
using Nethereum.Web3;
using Nethereum.Web3.Accounts;
var account = new Account("0xYOUR_PRIVATE_KEY", chainId: 31337);
var web3 = new Web3(account, "http://localhost:8545");
var receipt = await web3.Eth.GetEtherTransferService()
.TransferEtherAndWaitForReceiptAsync("0xRecipient", 0.1m);
Debug.Log($"TX: {receipt.TransactionHash}");
EIP-6963 discovers all installed browser wallets — MetaMask, Rainbow, Coinbase, etc.:
using Nethereum.Unity.EIP6963;
using Nethereum.EIP6963WalletInterop;
var walletProvider = EIP6963WebglHostProvider.CreateOrGetCurrentInstance();
// Discover all installed wallets
var wallets = await walletProvider.GetAvailableWalletsAsync();
foreach (var wallet in wallets)
Debug.Log($"Found: {wallet.Name} ({wallet.Rdns})");
// Select and connect
if (wallets.Length > 0)
{
await walletProvider.SelectWalletAsync(wallets[0].Uuid);
var account = await walletProvider.EnableProviderAsync();
Debug.Log($"Connected: {account}");
// Get Web3 — wallet handles signing
var web3 = await walletProvider.GetWeb3Async();
var balance = await web3.Eth.GetBalance.SendRequestAsync(walletProvider.SelectedAccount);
Debug.Log($"Balance: {Web3.Convert.FromWei(balance.Value)} ETH");
}
Events use Func<T, Task> delegates — handlers must return Task:
walletProvider.SelectedAccountChanged += async (newAccount) =>
{
Debug.Log($"Account switched: {newAccount}");
return; // implicit Task.CompletedTask
};
walletProvider.NetworkChanged += async (newChainId) =>
{
Debug.Log($"Network switched: {newChainId}");
return;
};
using Nethereum.Unity.Metamask;
var metamask = MetamaskWebglHostProvider.CreateOrGetCurrentInstance();
await metamask.EnableProviderAsync();
var web3 = await metamask.GetWeb3Async();
var receipt = await web3.Eth.GetEtherTransferService()
.TransferEtherAndWaitForReceiptAsync("0xRecipient", 0.1m);
Use built-in typed services — no ABI or code generation needed:
var erc20 = web3.Eth.ERC20.GetContractService(tokenAddress);
var name = await erc20.NameQueryAsync();
var symbol = await erc20.SymbolQueryAsync();
var decimals = await erc20.DecimalsQueryAsync();
var balance = await erc20.BalanceOfQueryAsync(ownerAddress);
Debug.Log($"{name} ({symbol}): {Web3.Convert.FromWei(balance, decimals)}");
Similarly, web3.Eth.ERC721 and web3.Eth.ERC1155 provide typed access to NFT and multi-token contracts.
Use conditional compilation to handle WebGL vs desktop:
private async Task<IWeb3> GetWeb3Async()
{
#if UNITY_WEBGL
var walletProvider = EIP6963WebglHostProvider.CreateOrGetCurrentInstance();
await walletProvider.EnableProviderAsync();
return await walletProvider.GetWeb3Async();
#else
var account = new Account(privateKey, chainId);
return new Web3(account, url);
#endif
}
Once you have IWeb3, all web3.Eth.* calls work identically regardless of platform.
Generate typed C# contract services from Solidity ABI:
dotnet tool install -g Nethereum.Generator.Console
Nethereum.Generator.Console generate from-abi \
-abi ./out/MyToken.abi \
-bin ./out/MyToken.bin \
-o ./SharedContracts \
-ns MyGame.Contracts \
-cn MyToken
Share the generated code between Unity and .NET test projects using a netstandard2.0 project with package.json + .asmdef files. Reference from Unity via file: dependency in manifest.json.
| Platform | Signing | Wallet Connection |
|---|---|---|
| WebGL | Browser wallet (EIP-6963, MetaMask) | EIP-6963 or MetaMask interop |
| Windows/macOS/Linux | Private key | RPC endpoint |
| iOS/Android | Private key | RPC endpoint |
For full documentation, see: https://docs.nethereum.com/docs/unity/overview