Nethereum 2.0.0 rc5 — Unity3d integration

Ethereum Flappy Unicorn

I am happy to report that the new release of Nethereum includes support for Unity3d, also you can play the demo game Ethereum Flappy Unicorn here.

Since I began working on Nethereum I have been very excited about the cross platform integration capabilities that .Net brings to Ethereum, including the capability of integration with games, VR and MR.

Combining the support for Urho3d by Xamarin, we can create already cross platform games as per the Nethereum game sample, and other exciting integrations of 3d elements with Xamarin applications including VR.

Nethereum was missing full support for Unity3d. Unity3d is one of the most widely used game, VR, MR engines, and it’s main scripting language is C#. To name a few, Unity supports development for Xbox, PS4, iOS, Android, UWP, Hololens, SamsungTV, WegGl, WebAssembly, etc, etc.

Sadly Unity3d is a completely different beast to work with. Unity3d still uses Mono targetting the old .net 3.51. The initial thought for Nethereum, was to wait until Unity3d engine was upgraded to the latest .Net, already on their roadmap. This seem like a good option as it was already possible to integrate Nethereum and Hololens using the latest version of .Net (at least using the emulator).

The past April (2017), the new beta release of Unity included the experimental support for the latest .Net, and I was happy to report it was working out of the box in Windows and Android. But, sadly the dependencies on the UnityWebRequest or www for WebGL, iOS and Il2cpp with coroutines still had no clear roadmap.

I decided then to bite the bullet, I will need to downport the libraries needed to .net3.5 and create a specific client library for Unity. At least, this way, anybody already working on Unity will be able to integrate with Ethereum.

Unity3d

If you are not familiar with Unity3d, the demo is based on the introduction tutorial to Unity3d.

You can find the Flappy Bird tutorial here: https://unity3d.com/learn/live-training/session/making-flappy-bird-style-game

And the Flappy bird source code here: https://assetstore.unity.com/packages/templates/flappy-bird-style-example-game-80330

The Nethereum source code can be found here: https://github.com/Nethereum/Nethereum.Flappy

Working with Unity3d

To enable cross platform compatibility and the threading mechanism using coroutines for Unity3d, Nethereum uses a new type of RPC Client, the UnityRpcClient.

All the Unity RPCRequests inherit now from this client, for example to retrieve the current blocknumber you will need to use:

EthBlockNumberUnityRequest

The UnityRpcClient similarly to other RPC providers accepts an RPCRequest, but internally uses UnityWebRequest which is compatible with Webgl and Il2Cpp.

Coroutines do not support any return values, to overcome this, the client inherits from UnityRequest, which provide the following properties:

public class UnityRequest<TResult> {
   public TResult Result { get; set; }
   public Exception Exception { get; set; }
}

All this UnityRPC requests, internally wrap the core RPC requests, decoupling the RPC clients but maintaining the integrity with the core requests.

Simple RPC calls

So how does this work? Let’s start with simple RPC calls, like the one to retrieve the current block number on the Ethereum Flappy Unicorn game.

Current block on Ethereum
var blockNumberRequest = new EthBlockNumberUnityRequest("https://rinkeby.infura.io");

Normally we would use web3 to manage all the RPC requests, but for Unity3d we use a specific request per each type of RPC call, including information about the RPC client. In this scenario the request is using as the RPC provider the Rinkbey public node provided by Infura.

When requesting a block number we don’t need any parameters, so we can simply just send the request and “yield” until it is complete.

yield return blockNumberRequest.SendRequest();

Once is completed, we can check for any errors and parse the result

if(blockNumberRequest.Exception == null) {
   var blockNumber = blockNumberRequest.Result.Value;
   blockNumberText.text = "Block: " + blockNumber.ToString();
}

Contract calls

Contract calls are made in a similar way to any other Unity RPC call, but they need the request to be encoded.

User top score

For example to retrieve the user top score we will create first a EthCallUnityRequest.

var userTopScoreRequest = new EthCallUnityRequest("https://rinkeby.infura.io");

Using the contract ABI and contract address we can then create a new contract and retrieve the function.

var contract = new Contract(null, ABI, contractAddress);
var function = new contract.GetFunction("userTopScores");

Note that the contract does not have now the generic RPC client as a constructor parameter.

The contract function can build the call input to retrieve the user top score.

yield return userTopScoreRequest.SendRequest(function.CreateCallInput(userAddress), Nethereum.RPC.Eth.DTOs.BlockParameter.CreateLatest());

Once we have retrieved the result successfully we use the function to decode the output.

function.DecodeSimpleTypeOutput<int>(userTopScoreRequest.Result);

Submitting Transactions

Before we submit the transaction we need to build the transaction input. For example to submit the user top score.

function.CreateTransactionInput(addressFrom, gas, valueAmount, score, v, r, s);

In this scenario the input parameters are the score, and the signature values for v, r, s.

Signing the transactions

There are many way that you can sign the transactions, as usual this depends on where the user stores their private keys and / or what is the best user experience.

An option, could be, that for Desktop and Mobile applications the user can open the web3 secrete storage definition file (account file in geth / parity) and sign the transaction with their private key.

var transactionSignedRequest = new TransactionSignedUnityRequest(_url, key, _userAddress);
yield return transactionSignedRequest.SignAndSendTransaction(transactionInput);

WebGL and Metamask

Decrypting using WebGL / JavaScript the account file is extremely slow, so when deploying a game to the browser, as per the Unicorn Flappy sample, it makes more sense to delegate the signing to Metamask.

To achieve this you can create your own external library to interact with the injected web3 library in the browser. For more information on External libraries check the Unity documentation

[DllImport("__Internal")]
private static extern string SendTransaction(string to, string data);

Uport

Finally, what happens if you want to sign a transaction when your screen is your TV and / or using your console, tvOS or Samsung TV. In this scenario displaying a QR integrating with Uport seems to be the best user experience.

Where to find the libraries

All the dlls necessary can be found in the Nethereum releases.

Just download the latest and put int your assets folder.

An example of all the scripts can be found in github, and if you want to build your own Flappy game just follow this Unity tutorials

Compiling to Webgl

When compiling to Webgl, you need to ensure that dlls are not stripped when running IL2CPP. An example of the link.xml file can be found in the flappy source code. You may find this issue if you encounter the error “No parameterless constructor defined for Nethereum.Unity.RpcModel.RpcParametersJsonConverter”.

Thanks

Many thanks to Jim Berry and Sarah Friend for the feedback and testing of the library. Also many thanks to Aaron (Kumavis), Karl Floersch and Andy Milenius for testing the game and providing feedback on the Metamask integration.

Like what you read? Give Juan Blanco a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.