Consumir una API REST desde Unity3D

Publicado por: Alonso | en Tutoriales | hace 12 meses | Comentarios

La popularidad que han ganado los servicios en la nube ha permitido que se desarrollen varias tecnologías que facilitan el acceso a dichos servicios a través de APIs, bien sea para consultar, manipular, crear o eliminar información alojada en la nube. Un ejemplo de esto sería un servidor web que almacene todos los puntajes de los usuarios registrados de un videojuego multiplayer, lo ideal es tener una forma de acceder a esa información e integrarla dentro de tu juego para que los usuarios puedan comparar sus puntuaciones con los demás.

La pregunta es: ¿Existe alguna forma de acceder a esa información sin depender de una página web?, respuesta: Si. A través del uso de APIs y para el caso de esta entrada de blog me centrare en como trabajar con información que viene de una API REST.

API REST a consumir

Con el objetivo de que cualquier persona que lea esto pueda realizar los ejemplos desde su computador y en la comodidad de su hogar u oficina, se usará una API REST pública que permite la ejecución de todas las operaciones que normalmente permite una API de este tipo.

JSONPlaceholder: https://jsonplaceholder.typicode.com/

GET y DELETE

Unity 3D actualmente permite consumir una API REST con mayor facilidad, gracias a un sistema añadido de manera experimental en Unity 5.X y estabilizadas en Unity 5.4 el nombre de este objeto es UnityWebRequest y se puede encontrar una explicación detallada aquí: https://docs.unity3d.com/Manual/UnityWebRequest.html

Nota: es necesario importar el objeto UnityWebRequest antes de realizar los ejemplos explicados más adelante, verificar como se importa dependiendo de la versión utilizada.

En esta guía sólo explicare como usar los métodos GET y DELETE, pero Unity soporta todos los demás métodos HTTP como POST, PUT, etc.

Ejecutando petición GET:

Para ejecutar una petición GET es necesario implementar el objeto UnityWebRequest dentro de un método que implemente la interfaz IEnumerator. A continuación un ejemplo:

    public IEnumerator GetPosts() {
        UnityWebRequest webRequest = UnityWebRequest.Get (

           "https://jsonplaceholder.typicode.com/posts"

       );
        yield return webRequest.Send ();

        if (!webRequest.isError) {

            Debug.Log(webRequest.downloadHandler.text);
        } else {
            Debug.Log (webRequest.error);
        }
    }

El método anteriormente expuesto al utilizar la interfaz IEnumerator se debe ejecutar de la siguiente manera:

StartCoroutine(GetPosts()); o StartCoroutine("GetPosts");

Si ejecutamos este código veremos la impresión de la información en la consola de Unity 3D

La información que viene de la API tiene un formato JSON pero Unity 3D lo trata como si fuese un string, por tal motivo existen utilidades para para convertir un string a JSON y viceversa.

Lo primero que se debe hacer es crear un clase Serializable con los datos que se quieren recibir desde la API, es importante aclarar que los nombres y tipos que se coloquen en la clase Serializable deben corresponder a los nombres y tipos que se reciben desde la API, como se muestra a continuación:

[System.Serializable]
public class PostSerializable {
    public int userId;
    public int id;
    public string title;
    public string body;
}

Nota: En caso de omitir algún atributo en la clase Serializable este será ignorado aún cuando se envíe desde el servidor en la estructura JSON.

En caso de ser una lista de objetos a recibir (el cual es nuestro caso), se debe crear una lista de objetos de tipo Serializable de la siguiente forma:

[System.Serializable] 
public class PostListSerializable { 
    public PostSerializable[] posts; 
}

Una vez hemos preperado todo nuestro código para convertir nuestro JSON a un objeto Serializable implementamos JsonUtility.FromJson en nuestro método GetPosts:

    public IEnumerator GetPosts() {
        UnityWebRequest webRequest = UnityWebRequest.Get (

           "https://jsonplaceholder.typicode.com/posts"

        );
        yield return webRequest.Send ();

        if (!webRequest.isError) {

            PostListSerializable postList = JsonUtility.FromJson<PostListSerializable>(

                webRequest.downloadHandler.text

            );
        } else {
            Debug.Log (webRequest.error);
        }
    }

Para este caso concreto deberíamos ver un error en la consola de Unity como el que se evidencia en la imagen.

¿Por qué?, esto se debe a que lo que realmente recibimos desde la API es una lista y no cumple en su totalidad con la notación JSON, la cual es así:

{"employees":[
    {"firstName":"John", "lastName":"Doe"},
    {"firstName":"Anna", "lastName":"Smith"},
    {"firstName":"Peter", "lastName":"Jones"}
]}

Para solventar este problema debemos implementar una pequeña utilidad que detallo a continuación:

    public string FixJson(string keyParent, string data){
        return string.Format("{{ \"{0}\": {1}}}", keyParent, data);
    }

Referencia: http://forum.unity3d.com/threads/how-to-load-an-array-with-jsonutility.375735/#post-2546117

Nuestro método GetPosts quedaría de la siguiente forma:

    public IEnumerator GetPosts() {
        UnityWebRequest webRequest = UnityWebRequest.Get (

           "https://jsonplaceholder.typicode.com/posts"

       );
        yield return webRequest.Send ();

        if (!webRequest.isError) {

            PostListSerializable postList = JsonUtility.FromJson<PostListSerializable>(

                FixJson("posts", webRequest.downloadHandler.text)

            );

            foreach (PostSerializable post in postList.posts) {
                Debug.Log(post.body);
            }

        } else {
            Debug.Log (webRequest.error);
        }
    }

Ahora tenemos una lista de objetos que podemos manipular como si de un objeto nativo de C# se tratase.

Si ejecutamos el Script deberíamos ver algo como esto en la consola, puesto que se
imprimieron los datos que viene en el atributo body

Ejecutando una petición DELETE:

    public IEnumerator DeletePost(int PostId) {
       string url = "https://jsonplaceholder.typicode.com/posts/";

        UnityWebRequest webRequest = UnityWebRequest.Delete (url + PostId + "/");
        yield return webRequest.Send ();

        if(webRequest.isError) {
            Debug.Log(webRequest.error);
        }
        else {
            Debug.Log("Delete completed!");
        }
    }

Resultado de ejecutar el método anterior

Caso de uso

En el video se puede observar una búsqueda y la posterior elimininación de un elemento dentro de la escena, ambas funcionalidades se realizan con la ayuda de una API REST utilizando el método GET y DELETE, el primero para traer la información reference al arból, el cual contiene una hoja que representa un artículo en la base de datos y el segundo para eliminar ese artículo (hoja) de la escena y borrarlo de la base de datos.

Para nuestra alegría en el Roadmap de Unity 3D se han contemplado varias mejoras para trabajar con API RESTs, las cuales serán implementadas a futuro.

Eso es todo... Espero que este breve explicación les sirva para facilitar sus procesos de integración de una API REST dentro de su proyecto.

Tengan todos un heroico día :D.

Comentarios

Búsqueda

Publicaciones recientes

Archivo

2017
2016
2015

Categorías

Editorial 3

Herramientas 4

Tutoriales 2

Etiquetas

GIT(1) Game Engine(4) Desarrollo(5) Audio(1) Unity3D(2) Linux(8) 3D(1)

Feeds

RSS / Atom

Enlaces Sociales

ubicación

Cartagena de Indias, Bolivar,
Colombia.

Template by Blacktie Mezzanine theme by CodingHouse