top of page

Let's Make an App (Part 2)

Updated: Nov 26, 2023

So once I got the application most of the way with Unity and MongoDB I stated trying to build the application on google Play Store and Apple App store. Unfortunately, what I released was once I had set the compiling the build to IL2CPP, the plugin for MongoDB stopped working. After researching more about the issue, I would have to redo the code by managing my own requests to the database, but because I was already managing user accounts and needed to manage authentication for the application and users, it was time to write an API for my app.





Why an API?


Who doesn't like the buzzword API?


The API allows us to do the computing of our back-end process on a remote server. This allows us to implement authentication processes, machine learning as well as other processes to make our application more dynamic.


The way I'm going to write this application is in FLASK python and will use a mixture of REST API calls as well as pass JSON bodies to the different GET, POST, and PUT endpoints.



Getting Started with FLASK


Flask

Getting started with flask, this is a simple example of how we start writing to a webpage based on a path.

import Flaskapp = Flask(__name__)

@app.route("/")
def hello():    
    return "Hello, World!"

What this does is if you open a browser or access the path at <port>/ you will find a print out of "Hello, World".

To do this lets select a port to run on and run the python script.

flask run
  * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Perfect! One of the nice features of flask is you can also pass variables into the route and be able to access it in the function itself.

@app.route('/<passed_variable>')
def show_some_variable(passed_variable):
    # show the user profile for that user
    return f' Some Variable :  {passed_variable}'

This is useful to be able to pass data in and out of your flask application. It's not the best method to manage the data in and out because they are in the path itself, but its good knowledge to have.


Now we can start making more distinct paths to run on. You can make app.route decorations for functions so they look like so:

@app.route("/do-something")
def do_something():    

This works, but it gets messy really quickly. How you start managing this in a larger code bases by using Flask blueprints.



Flask Blueprints


#example_blueprint.py

from flask import Blueprint
example_blueprint = Blueprint('example_blueprint', __name__)
@example_blueprint.route('/')
def index():
    return "This is an example app"

This can be used in the main application by linking the python file to the main file you run.

#main.py

from flask import Flask
from example_blueprint import example_blueprint
app = Flask(__name__)app.register_blueprint(example_blueprint)

Of course run this by using the flask run command.

flask run
  * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

Making the API

Next we want to make the API and start linking together the information coming in and out of it. We have the paths we want to run our data through but we will be using GET, POST, PUT and other endpoints to manage our data.

Another thing we are going to do is start passing in JSON data into our API endpoints. This allows us to be able to encode data and manage information in the header as part of our requests.


from flask import Flask, jsonify, request

app = Flask(__name__)

quotes= [{ 'quote': 'Not all who wonder are lost.', 'author': 'JRR Tolkien'}]

@app.route('/quotes')
def get_quotes():
    return jsonify(quotes)
    
@app.route('/quotes', methods=['POST'])
def add_quote():
    quotes.append(request.get_json())return '', 204

Now we have some basic understanding of the structure of making an API using flask, we can start filling out the essentials in our application.



Communicating to our Server


The next part of our process is writing functions for our API to call that can communicate to our servers. As outlined in my last tutorial, I used MongoDB and started linking the unity directly to the database. Unfortunately the library I used did not work on mobile platforms and for my purposes I wanted to move it into the cloud layer to better manage the data so information wasn't just hosted all on the device.


Python MongoDB (pymongo)

The repository for this package can be found here:


This library is easy to use and will work perfectly for most use-cases. The code below shows the example of linking to our database and then pulling information for one of our quotes.


from pymongo import MongoClient
client = MongoClient(<CONNECTION_STRING>)
db = client["database_name"]
collection = db["collection_name"]
collection.find_one()

This of course is a over simplification of how we can communicate to our server. What I ended up doing was creating a class that manages the database collection and it is then used between each collection database calls. Each one of these calls are done in a function that our API would reference to get the data necessary before sending it back to the user's interface.




Rewiring our Unity Application


Let me just say this process sucked. It took a long time, I had to move over every database lookup for authors, quotes, users and so much more from the application into the API, then I needed to make each API request go to the server and make sure the data was getting supplied properly and that the information received back from the API was readable and usable.


This is an example class for doing a get request from the API. What is happening is we are referencing the local server the the flask application is running on. Then we call the co-routine GetRequests with the route path and a callback function so we can handle the information from the API appropriately. It checks if the API sends back any errors and if it doesn't it returns the data to the callback. Perfect so we made our first API request from our application!



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

public class APIExample: MonoBehaviour
{
    public string apiUrl;
    
    public void Start()
    {
        apiUrl = "http://localhost:443";
    }
    
    public IEnumerator GetRequests(string route, Action<string> callback)
    {

    		UnityWebRequest request = UnityWebRequest.Get(apiUrl  + route);
    		yield return request.SendWebRequest();

    		if (request.result == UnityWebRequest.Result.ConnectionError || request.result == UnityWebRequest.Result.ProtocolError)
    		{
        		Debug.LogError("Error: " + request.error);
        		callback(request.error);
    		}
    		else
    		{
        		string responseJson = request.downloadHandler.text;
        		callback(responseJson);
    		}
	}
}
	


Conclusion


This is only the beginning of the journey I had to take to get my API up and running. As part of getting this running for production level application some of the other tasks you have to set up include:

  • Security and Authentication

  • Server hosting and management (Where is the API running)

  • Load balancing (How many requests are being made and how can it scale for more users.)

  • Much more....

Back end development is a whole career in itself with a lot of pitfalls and things that need to communicate to each other to make a functional system. One of the nice things about creating the API is that no matter what interface we use, (Godot, Unity, React, ect) we are managing our information, and in house tools separately so that the interfaces can become interchangeable based on the user's needs.


bottom of page