DEV Community

Cover image for Making a REST service using Node and Express to use with Unity - Part 1
Cem Ugur Karacam
Cem Ugur Karacam

Posted on

Making a REST service using Node and Express to use with Unity - Part 1

Making a game with unity is super cool. But what about online features like saving some data to a database like user info, progress, items, enemies...? You may familiar with node and rest api, but to sending a request from unity and handling received data is a bit itchy in unity.

So let's throw a blog series with unity and node. Then we gonna host it on heroku!

In this part we'll make our "Hello World" project.

Here is the project link on github.

If you've never heard about rest api, I recommend to first check out this tutorial to understand what it means.

Then, lemme write some code.

First open a terminal and initiate our node project file.

npm init
Enter fullscreen mode Exit fullscreen mode

Second, installing express.

npm install express
Enter fullscreen mode Exit fullscreen mode

Make our entry point. Let's call it app.js.

touch app.js
Enter fullscreen mode Exit fullscreen mode

Open the freshly created file with your favorite code editor(mine is vscode in this case) and import express.

const express = require('express');
const app = express();
Enter fullscreen mode Exit fullscreen mode

Our app should listen a port, 3000. Second parameter, a callback, write a message to console.

app.listen(3000, () => console.log('started and listening.'));
Enter fullscreen mode Exit fullscreen mode

One last step before run. When you ask to our app, we should respond back to user. In express this process stupidly simplified with below. When we hit localhost:3000 or make a call with postman our app will respond on certain endpoints. For the hello world project let's respond on home directory '/'.

If you're struggle with what an endpoint means or api ,http callback protocol, I recommend again to first check out this tutorial.

app.get('/', (req, res) => {
    res.send('Hello Unity Developers!');
})
Enter fullscreen mode Exit fullscreen mode

Let's take a look to our code before we run.

const express = require('express');
const app = express();

app.get('/', (req, res) => {
    res.send('Hello Unity Developers');
})

app.listen(3000, () => console.log('started and listening.'));
Enter fullscreen mode Exit fullscreen mode

Open a terminal and run the code.

node app.js
Enter fullscreen mode Exit fullscreen mode

Alt Text

If no error occured, we should see our console.log on terminal.

Now let's test it before switching to unity.
Go to your browser or postman to test our address localhost:3000.

Postman view

Browser view

Seems working!
So we have made a working service that replies when we ask. How do we do in unity?

Luckily unity have some http callback wrappers.

Let's open a fresh empty unity project and create an empty GameObject in our scene, rename it as 'client'.

Client GameObject

Now create a c# script in the Project folder, I'll name it ClientAPI.

ClientApi Script

In that script we should add a new namespace before we write any code.

using UnityEngine.Networking;
Enter fullscreen mode Exit fullscreen mode

Then we will define a method that returns an IEnumerator that enables async-like functionality in unity. If you're not sure how to use unity coroutines, this resource might be a good start.

public IEnumerator Get(string url)
{

}
Enter fullscreen mode Exit fullscreen mode

To make a web request let's define a new UnityWebRequest

public IEnumerator Get(string url)
{
    using(UnityWebRequest www = UnityWebRequest.Get(url))
    {

    }
}
Enter fullscreen mode Exit fullscreen mode

I'll put a link for why we need a using statement here. Also check-out unity docs for further reading.

This part is where couroutine magic involves. We should use yield return keyword when sending a request, it will make sure the process complete until it's done.

public IEnumerator Get(string url)
{
    using(UnityWebRequest www = UnityWebRequest.Get(url))
    {
        yield return www.SendWebRequest();
    }
}
Enter fullscreen mode Exit fullscreen mode

Afterwards, check for errors.

public IEnumerator Get(string url)
{
    using(UnityWebRequest www = UnityWebRequest.Get(url))
    {
        yield return www.SendWebRequest();

        if (www.isNetworkError)
        {
            Debug.Log(www.error);
        }
        else
        {

        }
    }
}
Enter fullscreen mode Exit fullscreen mode

If no errror, then it's completed succesfuly.

We have revieved some data from http connection but we should parse these as a string to further work. We'll feed the data as www.downloadHandler.data from our api. Return our parsed data as string.

public IEnumerator Get(string url)
{
    using(UnityWebRequest www = UnityWebRequest.Get(url))
    {
        yield return www.SendWebRequest();

        if (www.isNetworkError)
        {
            Debug.Log(www.error);
        }
        else
        {
            if (www.isDone)
            {
                // handle the result
                var result = System.Text.Encoding.UTF8.GetString(www.downloadHandler.data);
                Debug.Log(result);
            }
            else
            {
                //handle the problem
                Debug.Log("Error! data couldn't get.");
            }
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

And define a public variable to provide url.
Now let's give it a go, call our method on Start. To use coroutines, we have to call it as StartCoroutine() otherwise it won't work.
Take a look to whole script.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class ClientApi : MonoBehaviour
{
    public string url;

    void Start()
    {
        StartCoroutine(Get(url));
    }

    public IEnumerator Get(string url)
    {
        using(UnityWebRequest www = UnityWebRequest.Get(url)){
            yield return www.SendWebRequest();

            if (www.isNetworkError)
            {
                Debug.Log(www.error);
            }
            else
            {
                if (www.isDone)
                {
                    // handle the result
                    var result = System.Text.Encoding.UTF8.GetString(www.downloadHandler.data);
                    Debug.Log(result);
                }
                else
                {
                    //handle the problem
                    Debug.Log("Error! data couldn't get.");
                }
            }
        }

    }
}
Enter fullscreen mode Exit fullscreen mode

Jump back to the unity editor and add script to client GameObject.

Attach Script

Next, enter our address to url.

Provide url

Now hit play.

Debug.Log image

We should see the message on the console if you succeeded.

Wow! isn't that cool?

Our server and unity client works like a charm. Congrats!

Here is the project link on github.

BONUS

Let's add some trailer images to make some hype about next parts :)

postman result orc

Unity client url

Debug.Log result

Top comments (11)

Collapse
 
hungvt profile image
hung-vt

can you make a tutorial using nodejs and socket.io in unity, please

Collapse
 
cemuka profile image
Cem Ugur Karacam

Unfortunately, socket.io wrappers for unity on assetstore and github are abandoned or debrecated. Paid packages available but I don't prefer them for a blogpost tutorial.

Let me know if you find an updated non-paid version for unity.

Collapse
 
quiphop profile image
Konstantin

Try Colyseus
I'm already use it, pretty neat

Collapse
 
cemuka profile image
Cem Ugur Karacam

Thanks for the suggestion, looks promising. I'll dig in!

Collapse
 
kristijanfistrek profile image
KristijanFištrek

My guy, when is the second part dropping? 😄
This is really cool and I would love to learn more!

Collapse
 
cemuka profile image
Cem Ugur Karacam

Thanks man👍! I'll make it quick asap 😎🤓

Collapse
 
sinteticwizard profile image
Ramon Ramirez

nice

Collapse
 
cemuka profile image
Cem Ugur Karacam

thanks!🤗

Collapse
 
wickedknock profile image
wickedknock

Thanks man really appreciate it. Good stuff!

Collapse
 
cemuka profile image
Cem Ugur Karacam • Edited

Good to hear positive feedback. Thanks for it :)

Collapse
 
supremepanda profile image
Furkan Baldır

Thanks for the useful content.