The IC Gallery
Published in

The IC Gallery

A Unity Game Template for the Internet Computer

Created by Tommy from The IC Gallery

Hello there! If you’re a game developer looking to create a game hosted on the Internet Computer blockchain, you’re in luck. I’ve created a simple Unity project showcasing wallet integration and fetching NFTs — just for you. Now you can get started working on the actual “fun” parts of your game, rather than worrying about how to call browser Javascript from Unity C#.

You can view this demo of wallet integration at: https://ti5gm-bqaaa-aaaai-ab7oa-cai.raw.ic0.app/

And the project code at: https://github.com/tommygames/ic-unity-template

Image of the IC Unity Template running in a canister
IC Unity Template Demo

NOTE: This project integrates an npm module called react-unity-webgl in order for Unity C# to communicate with browser Javascript for Plug Wallet integration. If you don’t need wallet integration or Javascript interoperability, then do not follow this guide, as there are easier ways to deploy a simple Unity game to the IC.

If you want to know how I setup the project from scratch, skip to the Creating an IC Unity Project from Scratch section.

If you’d rather just download and deploy the Unity project, skip to the Deploy the IC Unity Project section.

And if you want to understand how the code works, read the following How Does It All Work section.

How Does It All Work

There are 2 functionalities needed for Plug Wallet integration to work:

  1. Unity C# dispatches events to browser Javascript
  2. Browser Javascript dispatches events to Unity

For both of these, we use an npm module called react-unity-webgl. The documentation for it can be found here: https://www.npmjs.com/package/react-unity-webgl

For the 1st functionality, we use .jslib plugins in Unity that allow us to write pseudo-Javascript (often called UnityScript). Read more about it here: https://docs.unity3d.com/Manual/webgl-interactingwithbrowserscripting.html

If you have the react-unity-webgl module installed, these .jslib plugins can dispatch events to the React browser Javascript by calling dispatchReactUnityEvent("EventName") You can see this implemented in the PlugUtils.jslib file in the Unity project. To call these functions, you have to import them into C#. An example of this can be seen in the PlugUtilsInternal class in the PlugUtils.cs file.

For the 2nd functionality, we call unityContext.send("GameObjectName", “FunctionName", jsonData) from our React javascript code. You can see this implemented in the PlugUtils.js class in our React app.

This will call the specified function on the specified GameObject. For my example, I have a GameObject in my MainScene called ReactApi with a script containing a function called HandleCallback

Because I wanted to have callbacks whenever Unity talks to the browser Javascript, I store a dictionary of callbacks associated with their index in the ReactApi.cs file. That way, any communication between Unity and React has to go through the ReactApi file and callbacks will be triggered when the JSON data is returned.

Once the JSON data is returned, I use Json.NET to deserialize the data into an object. These objects are defined in the WalletDataTypes.cs file.

If the JSON data is deserialized successfully, it displays it to the UI! And that’s how it all works :)

Deploy the IC Unity Project

  1. Download the project files from: https://github.com/tommygames/ic-unity-template
  2. Make sure you have the Dfinity Canister smart contract SDK installed (I’m using version 0.9.3 for this project): https://smartcontracts.org/docs/developers-guide/install-upgrade-remove.html
  3. cd into the ic_unity_template folder within the Unity project (this contains the dfx project).
  4. Run npm install and make sure all the node modules are installed correctly. You may have to follow specific instructions to make sure the dab-js node module is installed correctly. Instructions can be found here: https://docs.dab.ooo/nft-list/getting-started/
  5. Run dfx start --background inside the ic_unity_template folder to start your local IC environment in the background. Run dfx deploy to deploy the IC canister to the local IC environment. Once it is finished deploying, it will tell you a URL that you can visit the project at!
  6. To deploy the project to the mainnet public blockchain network, you need to cd into the ic_unity_template folder and run dfx deploy --network=ic Once deployed, it will tell you the canister id of the ic_unity_template_assets canister. You can access the project by going to https://<canister_id>.raw.ic0.app/

NOTE: It is very important you include the “raw” keyword in the URL as Unity files are very large and can only be served using this keyword.

If you make changes to the Unity project and re-build it, make sure to name your build unity_build. After it finishes building, drag the Build, TemplateData, and StreamingAssets (if exists) folders into your src/ic_unity_template_assets/assets folder (you can ignore the index.html file). Then you can re-deploy to the canister!

Thanks for reading this far! That’s how you deploy the sample Unity project with react-unity-webgl integration in order to make calls between Javascript and C#. I hope you enjoyed reading and wish you the best of luck in your game dev adventures! Feel free to reach me @tommyinvests on twitter. I’m the lead developer of the IC Gallery project. We are looking for Unity devs to join us, send me a DM if you’re interested! :)

Creating an IC Unity Project from Scratch

  1. Create a new Unity project.
  2. Download and install the Dfinity Canister smart contract SDK: https://smartcontracts.org/docs/developers-guide/install-upgrade-remove.html
  3. dfx is the primary command line tool that’s used to spin up new Dfinity projects, and it auto-fills the project with template code. Documentation can be found here: https://smartcontracts.org/docs/developers-guide/cli-reference.html
  4. Open the command line and cd into your Unity project folder. Then run dfx new project-name-goes-here to create a new template project called “project-name-goes-here”. This creates a new dfx project within your Unity project folder. NOTE: You don’t necessarily have to create the dfx project within your Unity project folder, you can also have them be in separate folders.
  5. Next you need to modify the template dfx project to be compatible with the React web framework.
  6. We’ll use the React framework as a wrapper around our Unity project to allow for messages to be sent between the React javascript code and Unity C#. This enables wallet integration and also gives you the flexibility of having web components (in React) be overlayed on top of your game in the future (if you wish).
  7. I followed this Dfinity guide to make my project React compatible: https://smartcontracts.org/docs/developers-guide/tutorials/custom-frontend.html NOTE: You don’t need to follow all the steps in the guide. Just do the following steps:
  • Run npm install --save react react-dom in your project folder
  • Run npm install --save-dev typescript ts-loader in your project folder
  • Open webpack.config.js and add this code above the plugins section:
module: {rules: [{ test: /\.(js|ts)x?$/, loader: "ts-loader" }]},
  • Create a new file named tsconfig.json in the root directory for your project and paste this code into it:
{“compilerOptions”: {“target”: “es2018”, /* Specify ECMAScript target version: ‘ES3’ (default), ‘ES5’, ‘ES2015’, ‘ES2016’, ‘ES2017’, ‘ES2018’, ‘ES2019’ or ‘ESNEXT’. */“lib”: [“ES2018”, “DOM”], /* Specify library files to be included in the compilation. */“allowJs”: true, /* Allow javascript files to be compiled. */“jsx”: “react”, /* Specify JSX code generation: ‘preserve’, ‘react-native’, or ‘react’. */},“include”: [“src/**/*”],}

8. Once you’ve set up your dfx project to be compatible with React, you need to create the React project files. I used the “Create React App” command line tools to spin up a default React project: https://reactjs.org/docs/create-a-new-react-app.html

9. Once your React project is created, copy the index.html, index.js, index.css, App.js, App.css, and any other relevant files from your React project src folder to the src/project_name_assets/src folder of your dfx project. These are where all your private files will live. You’ll also notice an assets folder next to the src folder. This is where all your public files will live, including your Unity build files.

10. Once you’ve copied your React files into the dfx project, you’ll need to make sure the following npm modules are installed for your project:

11. The react-unity-webgl module is very important as it allows us to send events between React and Unity. These events will allow Unity to interact with browser Javascript and connect to Plug Wallet. You can find documentation for it here: https://www.npmjs.com/package/react-unity-webgl

You can install it by running this in your dfx project folder:

npm install react-unity-webgl

Once it is installed, follow the instructions in the react-unity-webgl documentation to modify your App.js file. A basic implementation of App.js looks like this:

import React from "react";
import Unity, { UnityContext } from "react-unity-webgl";
const unityContext = new UnityContext({
loaderUrl: "Build/myunityapp.loader.js",
dataUrl: "Build/myunityapp.data",
frameworkUrl: "Build/myunityapp.framework.js",
codeUrl: "Build/myunityapp.wasm",
});
function App() {
return <Unity unityContext={unityContext} />;
}
export default App;

12. The dab-js module is a library that Psychedelic created to help us query their NFT database. This will allow us to fetch all the NFTs that are currently in a user’s Plug Wallet. NOTE: The installation process for this npm module is a bit more complicated. You will need to create a Github access token and sign in before downloading the module. Please follow the instructions here: https://docs.dab.ooo/nft-list/getting-started/

13. Finally, you’ll need to ensure that your @dfinity/agent , @dfinity/principal , and @dfinity/candid npm modules are using version 0.9.3 or below. This is because the dab-js module currently only supports those versions or below due to Principal Id encoding changes. You can run these commands to ensure that version:

npm install @dfinity/agent@0.9.3
npm install @dfinity/principal@0.9.3
npm install @dfinity/candid@0.9.3

14. Now you need to build your Unity project. Open Unity and go to File->Build Settings and switch to the WebGL platform.

15. Then go to Edit->Project Settings and set “Compression Format” to Disabled. IC Canisters currently do not support Gzip or Brotli compression formats.

16. Finally, go back to Build Settings and tap the “Build” button. What you specify as the name of your build will also change the prefix of your build files. Let’s call ours “BestGame”. Once you finish the build, drag the Build, TemplateData, and StreamingAssets (if exists) folders into your src/project_name_assets/assets folder in your dfx project (you can ignore the index.html file). Then you’ll need to go back to Step 11 and edit your App.js to have the correct file paths to your build files. If our build name was “BestGame” then our App.js file would look like this:

import React from "react";
import Unity, { UnityContext } from "react-unity-webgl";
const unityContext = new UnityContext({
loaderUrl: "Build/BestGame.loader.js",
dataUrl: "Build/BestGame.data",
frameworkUrl: "Build/BestGame.framework.js",
codeUrl: "Build/BestGame.wasm",
});
function App() {
return <Unity unityContext={unityContext} />;
}
export default App;

17. Once you’ve finished this step, you’re ready to upload your game to the IC! cd into your dfx project folder and run dfx start --background which will start the local IC environment in the background. Then run dfx deploy which will deploy your IC Unity game to the local IC environment. Once it is finished deploying, it will tell you a URL that you can visit your game at!

18. To deploy your IC game to the mainnet public blockchain network, you need to cd into your dfx project folder and run dfx deploy --network=ic Once deployed, it will tell you the canister id of the project_name_assets canister. You can access your game by going to https://<canister_id>.raw.ic0.app/

NOTE: It is very important you include the “raw” keyword in the URL as Unity files are very large and can only be served using this keyword.

Thanks for reading this far! That’s how you create and deploy a Unity project to a canister with react-unity-webgl integration in order to make calls between Javascript and C#. I hope you enjoyed reading and wish you the best of luck in your game dev adventures! Feel free to reach me @tommyinvests on twitter. I’m the lead developer of the IC Gallery project. We are looking for Unity devs to join us, send me a DM if you’re interested! :)

--

--

--

Articles related to IC Gallery game world on the Internet Computer blockchain. We believe in creating life-changing opportunities through gaming and NFTs.

Recommended from Medium

https://t.co/qLxqq2ycSJ

The Reversal Indicator — Coding in Python.

Magic Leap: C++ Tutorial Part 3

Moltres Goes Berserk!

How to Develop an Image Editing App with Image Kit? — Part 1

For paint brush, painting green, red, orange and blue top to bottom.

Tide.co: Migrating from Redshift to Snowflake

MY LINUX EXPERIENCE!

10-Minute Guide to Julia For Die-Hard Python Lovers

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Tommy M

Tommy M

Lead Developer of the IC Gallery on the Internet Computer blockchain.

More from Medium

What’s the ICPlaza(ICT)?

New Releases: ICNS-js & Shortlink Profiles

How to add DONGE token to supported wallets in ICP

Dominic: How Internet Computers Bring 1 Billion Users to Blockchain