DEV Community

loading...

Trying out GraphQL with Unity3d engine

Vladimir Novick
Software Architect & consultant (available for consulting), worldwide speaker, published author, workshops teacher and developer in Web/Cloud/Mobile/AR/VR/IoT/AI/Blockchain fields
・4 min read

GraphQL is an amazing technology that took the world like a storm. More and more companies are switching to using GraphQL instead of REST APIs because so many things, GraphQL solves.

In a nutshell, GraphQL is a query language for your API. It gives you an ability from a client-side to query your single API endpoint and define a shape of data that you want to get. On the server, you define a schema - the shape of data and how this data is resolved. Whether from a database, microservices or literally in any way you want.

What's also cool, GraphQL gives you subscriptions functionality so you can get real-time data over WebSockets and build modern web and mobile apps with ease. If you are interested to learn more about GraphQL, you can check out learn.hasura.io tutorials on how to use GraphQL with lots of various web and mobile clients.
Also, you can check GraphQL Bootcamp I did some time ago on my Youtube channel

If you've been following me on twitter @VladimirNovick you probably know that I am working on Web, Mobile, AR, VR and IoT fields.

In VR and AR fields especially I've been working with Unity3d engine, so I was recently curious whether I can use GraphQL in Unity3d for things like real-time leaderboards.

After a long search for a graphql client for Unity3d, which I can use in C# and which will be supported in Unity engine, I found really basic one, that I used for the following demo.

So what's happening in this demo?
There are 3 scenes, which I have:

First one is just a loading screen and here I just show basic Loading screen with 10 seconds timer. So nothing really happening here.

Next loaded screen is HasuraSpaceDemo

I used FPS All in One first-person controller and Sci-Fi Modular corridor demo scene. For the portal, I used KTK Lighting asset to reduce time working on particle effects, but basically, it's just the Unity Shuriken particle system using a bunch of lighting assets. For UI and for Portal scene I used Sci fi UI pack and Living particles. Music in the scene is from Dark Sci-fi asset

HasuraSpaceDemo is used to showcase that GraphQL can be used in any type of game. If you walk into the portal I present UI where you can basically enter any GraphQL endpoint URL. When you do so, you are "teleported" into different - Portal scene.

I have UIManager script that handles UI:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UIManager : Singleton<UIManager>
{
    public string graphQLEndpoint;
    public GameObject graphQLCanvas;

    private void Start()
    {
        DontDestroyOnLoad(gameObject);
    }


    // Start is called before the first frame update
    public void LoadPortalScene()
    {
        GameManager.Instance.loadPortalScene();
    }

    public void setGraphQLEndpoint(Transform inputField)
    {
        graphQLEndpoint = inputField.GetComponent<InputField>().text;
    }

}

Enter fullscreen mode Exit fullscreen mode

As you can see this script has two public methods - first one to load the portal scene and the second one to set graphQLEndpoint for later use in the next scene.

To use GraphQL in the next scene, what I do is, first of all, use GraphQLQuery script from graphql-client-unity package and set it on new empty Game Object in the scene calling it GraphQLClient

Then I need to add a Panel that will have interaction. The idea is when I approach a panel with text "GraphQL Schema Introspection", I will enter into Box Collider which will trigger OnTriggerStay method in IntrospectionPanelInteraction script.

When our IntrospectionPanelInteraction script starts, we set our GraphQuery URL, canvas to display a result as well as canvas content:

    void Start()
    {
        if (UIManager.Instance)
        {
            UIManager.Instance.graphQLCanvas = canvas;
        }

        GraphQuery.url = UIManager.Instance.graphQLEndpoint;

        fp = FindObjectOfType<FirstPersonAIO>();
        content = canvas.GetComponent<UICanvas>().Content;
    }
Enter fullscreen mode Exit fullscreen mode

So when we are within Collider borders, OnTriggerStay function is running.


    private void OnTriggerStay(Collider other)
    {
        if (!canvas.activeSelf)
        {
            canvas.SetActive(true);
            runIntrospectionQuery();
        }
        InteractionController.Instance.disableInteraction(fp);
    }
Enter fullscreen mode Exit fullscreen mode

query execution looks like this:

    void runIntrospectionQuery()
    {
        Debug.Log("Query");
      GraphQuery.onQueryComplete += DisplayResult;
      GraphQuery.POST(introspectionQuery);

    }
Enter fullscreen mode Exit fullscreen mode

the query itself is defined as a string public variable and is visible in the editor:

The final IntrospectionPanelInteraction script looks like this:

using System.Collections;
using System.Collections.Generic;
using graphQLClient;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.UI;

public class IntrospectionPanelInteraction : MonoBehaviour
{

    [Tooltip("This is the query call that gives me introspection details)]
    [TextArea]
    public string introspectionQuery;

    public GameObject canvas;
    private FirstPersonAIO fp;
    private Text content;
    void Start()
    {
        if (UIManager.Instance)
        {
            UIManager.Instance.graphQLCanvas = canvas;
        }

        GraphQuery.url = UIManager.Instance.graphQLEndpoint;

        fp = FindObjectOfType<FirstPersonAIO>();
        content = canvas.GetComponent<UICanvas>().Content;
    }
    // Start is called before the first frame update
    private void OnTriggerStay(Collider other)
    {
        if (!canvas.activeSelf)
        {
            canvas.SetActive(true);
            runIntrospectionQuery();
        }
        InteractionController.Instance.disableInteraction(fp);
    }

    private void OnTriggerExit(Collider other)
    {
        if (canvas.activeSelf)
        {
            canvas.SetActive(false);
            InteractionController.Instance.enableInteraction(fp);
        }
    }

    void runIntrospectionQuery()
    {
        Debug.Log("Query");
        GraphQuery.onQueryComplete += DisplayResult;
        GraphQuery.POST(introspectionQuery);

    }

    public void DisplayResult()
    {
        string data = ParseData(GraphQuery.queryReturn, "__schema");
        canvas.gameObject.GetComponentInChildren<ScrollRect>().normalizedPosition = new Vector2(0, 1);
        Debug.Log(data);
        content.text = data;
    }

    void OnDisable()
    {
        GraphQuery.onQueryComplete -= DisplayResult;
    }

    string ParseData(string query, string queryName){
        JObject obj = JsonConvert.DeserializeObject<JObject>(query);
        return JsonConvert.SerializeObject(obj["data"][queryName], Formatting.Indented);
    }

}

Enter fullscreen mode Exit fullscreen mode

Summary

As you can imagine this is a very simple example and it's me just trying out GraphQL in Unity engine. Also, it's a long way to go to get subscriptions, live queries etc. I am experimenting and I would love to see what use case for GraphQL in Unity3d or Unreal engine will be. I can see it really useful for things like leaderboards, high scores, in-app purchases, in-game ads, etc.

Please let me know on Twitter what GraphQL usage you see in Unity3d.

Discussion (1)

Collapse
gazuntype profile image
Tade Ajiboye

hey! @gazuntype here, the creator of the GraphQL client you used. Just wanted to inform you that i've made some major changes to the client and it's now significantly more convenient to use.