Unity and Ethereum: Why and How

Ethereum has great potential for gaming. In this tutorial you will learn why Ethereum is interesting for you as a game developer. By Kevin Small.

4 (4) · 1 Review

Download materials
Save for later
Share
You are currently viewing page 3 of 4 of this article. Click here to view the first page.

Getting Some Ether Into Your Ethereum Account

On the live Ethereum network, you buy Ether with normal currency, often using online exchanges. Testing software with real money is not a good idea. To get some free Ether into your test account you use a faucet by following these steps:

screen08.jpg

screen07.jpg

screen05.jpg 

  1. Copy your address from MetaMask by clicking on the triple ellipsis and choosing Copy Address to Clipboard just like you did above.
  2. Tweet your address like in this example. You can also make a public Facebook post or a public Google Plus post.
  3. Go to the Rinkeby faucet site and paste in the link to the social media post you just made. Use the dropdown on the right of the screen to choose how much Ether you want to receive:

After a few seconds, you’ll see an acknowledgement:

screen06.jpg 

screen09.jpg 

  1. Wait for another 20 seconds or so, and then check your balance. You can check your balance in MetaMask; it’s the amount of Ether (ETH) at the bottom left here:

Reading An Account Balance

You are solvent on the test network! Now you will see how Unity can read your balance. In the HighScoreController.cs file, add some additional using statements to the top of the file:

using System.Numerics;
using Nethereum.Hex.HexTypes;
using Nethereum.JsonRpc.UnityClient;

Replace the contents of GetAccountBalanceCoroutine with this code:

public IEnumerator GetAccountBalanceCoroutine()
{
   var getBalanceRequest = new EthGetBalanceUnityRequest(networkUrl);           // 1
   // Send balance request with player's account, asking for balance in latest block
   yield return getBalanceRequest.SendRequest(playerEthereumAccount, Nethereum.RPC.Eth.DTOs.BlockParameter.CreateLatest());  // 2

   if (getBalanceRequest.Exception == null)                                     // 3
   {
      var balance = getBalanceRequest.Result.Value;                             // 4
      // Convert the balance from wei to ether and round to 8 decimals for display                                
      uiTextEtherBalance.text =
        Nethereum.Util.UnitConversion.Convert.FromWei(balance, 18).ToString("n8");    // 5
   }
   else
   {
      Debug.Log("RW: Get Account Balance gave an exception: " + getBalanceRequest.Exception.Message);
   }
}

The numbered notes in the code above show it performing these steps:

  1. The script creates a new Nethereum request passing in the network you are using.
  2. The script sends the request asynchronously, passing in parameters identifying the player’s Ethereum account and saying what block number you want the balance at. You want the latest, most recent block.
  3. The script checks for an error in the call.
  4. The script extracts the balance.
  5. The Ethereum network generally records Ether values in a unit called Wei. It takes a billion, billion Wei to make up one Ether, so you need to do a unit conversion to get the Ether value to display.

Play the scene. Press the Refresh button and wait a few seconds. The balance gets displayed just underneath the high score table:

screen10.jpg

Preparing To Interact With The High Score Contract

Now you’re going to connect the game to a smart contract that records the top 40 high scores. The smart contract is written in the language Solidity.

Your first step is to create a C# wrapper around the Solidity contract to make it easy to interact within your C# code. In your code editor, open the HighScoreContractWrapper.cs file from the Assets\RW\Scripts folder.

The first comment block is the copyright notice. The second comment block you should uncomment. Remove /* on line 30 and */ at the end of the file. Save the file. The end result will be like this:

/*
 * Copyright (c) 2018 Razeware LLC
...
*/
...
using Nethereum.ABI.Encoders;
using Nethereum.ABI.FunctionEncoding.Attributes;
...
   [Parameter("int256", "score", 2)]
   public BigInteger Score { get; set; }
}

To get an idea of how the contract works, you can browse the contract source code. You can see it stores a public array of high scores and exposes a function to receive a new high score value named setTopScore. The C# wrapper HighScoreContractWrapper.cs provides you with a C# method CreateSetTopScoreTransactionInput that you can use to send a new high score to the smart contract.

Note: Understanding the detail behind the C# wrapper script and the smart contract is beyond the scope of this tutorial. See the links at the end of this tutorial if you’d like to learn more.

Go back to editing HighScoreController.cs again. In the global data part near the top of the file, add two new private variables:

private HighScoreContractWrapper scoreContractService;
private HexBigInteger gasLimit = new HexBigInteger(4712388);

The first is a reference to the C# wrapper; the second one represents the most you want to spend on a transaction. The concept of gas is not covered in this tutorial, but you can think of it as Ether.

At the end of Start, add these lines:

// Service for interaction with high score contract
scoreContractService = new HighScoreContractWrapper();

Ethereum makes use of 256-bit integers, which needs a data type not available in Unity as standard. Find the PrettifyScore method, and change its signature to receive a BigInteger instead of an int:

private string PrettifyScore(BigInteger score) ...

Save everything, switch to Unity and make sure the project compiles.

Next, you’ll read the high score contract.

Retrieve High Scores From Ethereum

Switch back to your code editor. Find the method GetHighScoresCoroutine, and replace its body with:

public IEnumerator GetHighScoresCoroutine()
{
   var topScoreRequest = new EthCallUnityRequest(networkUrl);                         // 1
   // Use the service to create a call input
   var countTopScoresCallInput = scoreContractService.CreateCountTopScoresCallInput();
   // Call request sends and yield for response  
   yield return topScoreRequest.SendRequest(countTopScoresCallInput, 
     Nethereum.RPC.Eth.DTOs.BlockParameter.CreateLatest());                           // 2

   // Decode the top score using the service
   var scores = new List<HighScoreDataTypeDefinition>();
   var count = scoreContractService.DecodeTopScoreCount(topScoreRequest.Result);      // 3
   Debug.Log("RW: High Score count: " + count);
   for (int i = 0; i < count; i++)
   {
      topScoreRequest = new EthCallUnityRequest(networkUrl);                          // 4
      var topScoreCallInput = scoreContractService.CreateTopScoresCallInput(i);
      yield return topScoreRequest.SendRequest(topScoreCallInput, 
        Nethereum.RPC.Eth.DTOs.BlockParameter.CreateLatest());
      scores.Add(scoreContractService.DecodeTopScoreDTO(topScoreRequest.Result));
   }

   var orderedScores = scores.OrderByDescending(x => x.Score).ToList();               // 5
   var topScores = "";
   foreach (var score in orderedScores)                                                       
   {
      string playerAddress = PrettifyAddress(score.Addr);
      string playerSCore = PrettifyScore(score.Score);
      topScores = topScores + playerSCore + " : " + playerAddress + Environment.NewLine;
   }
   uiTextHighScores.text = topScores;
}

The code performs these steps:

  1. The script creates a new Nethereum request.
  2. The script sends the request asynchronously, passing in parameters identifying the smart contract method we want to call.
  3. The script checks to see how many top scores there are.
  4. The script extracts details for each top score one at a time.
  5. The script sorts the score and makes each high score entry a pretty format to display on screen.

Play the scene, press refresh, wait a few seconds and the list of high scores appears:

screen_refresh_01.jpg