Cómo aumentar el rendimiento de tu equipo en Unity

Uno de los mayores dolores de cabeza siempre han sido las builds del proyecto. Seguro que habéis vivido alguna de estas situaciones: sin previo aviso el jefe te pregunta por la ultima build porque se va a reunir con unos inversores y la necesita ya; el equipo de QA necesita una build nueva porque la que tienen no contiene todos los cambios; que te vengan a buscar a primera hora porque necesitamos una build en 15 minutos.

Por suerte las tools que se encargan de esto han evolucionado mucho, ahora podemos programar el sistema para que cada vez que el desarrollador suba un cambio se genere una build con los ultimos cambios. O que cada día al final del día se genere una build con todos los cambios para que esté disponible a primera hora. O que el propio jefe/diseñador/QA pueda lanzar una build con los últimos cambios y recibir en su correo cuando está disponible.

Todo eso lo podemos conseguir de forma fácil y totalmente gratuita con GitHub actions para Unity. Con esta herramienta podremos configurar nuestro propio servidor de integración continua (CI) y quitarnos todos esos problemas aumentando así la efectividad y rendimiento de nuestro equipo.

En este post vamos a ver que es un servidor de CI/CD y cómo configurar uno con GitHub actions y Unity de la forma más sencilla, y sin gastarnos un euro.

¿Qué es la integración continua o Continuos Integration (CI)?

Según Wikipedia la integración continua, o continuous integration, es una práctica de software que consiste en hacer integraciones automáticas de un proyecto lo más a menudo posible para así poder detectar fallos cuanto antes.

Básicamente terminas tu trabajo, la feature en la que estás trabajando, o una parte de esta, y quieres que de forma automática se suba a la rama principal, pero antes quieres que se compile y ejecute todos los tests para asegurarte de que está todo ok y no rompes nada.

¿A cuántos os ha pasado que subáis una cosa al proyecto y por lo que sea no habéis probado en todas las plataformas y resulta que en Android funciona pero en iOS no?
O al contrario os bajáis lo último del repo y veis que no compila porque vuestro compañero la ha liado.
Si no os ha pasado y no tenéis un servidor de integración continua solo es cuestión de tiempo, ser pacientes que acabará explotando 😜.

Esto es exactamente lo que intenta evitar la integración continua.

¿Qué es un servidor de integración continua?

Es un servicio que detecta cuando queremos hacer merge de nuestra rama a la rama principal y entonces empieza a ejecutar toda la magia: compila el proyecto en todas las plataformas, ejecuta los tests y si funciona podemos hacer que el mismo haga el merge y si falla podemos hacer que nos notifique.

La idea de esto no es señalar que ha fallado, la idea es que no se nos cuelen errores que podamos evitar y detectarlos lo antes posible.

Además de detectar cuando vamos a hacer un merge podemos hacer que detecte cada vez que hacemos un commit, o abrimos un pull request y prácticamente todas las acciones que hagamos con git.

La verdad es que se vive mucho más tranquilo sabiendo que hay un sistema comprobando que no la has liado, dentro de sus limitaciones claro, y también se le puede configurar para que si todo va bien genere una build con los últimos cambios. De esta forma con cada merge tendremos una build jugable con los últimos cambios y de forma automática.

¿Qué es la entrega continua o Continuos Delivery (CD)?

El siguiente nivel a la integración continua es la entrega continua, o continuous delivery, que básicamente tiene lo mismo que la integración continua pero le añadimos un paso más, y este paso no es otro que publicar directamente el juego en las stores 😁.

En el caso de aplicaciones o juegos que tienen que pasar por una store como la de Android y iOS, el proceso es un poco más complejo pero hay formas de automatizar para que la build generada se firme y se suba directamente al apartado de testing de la store.

Para aplicaciones web esto es bastante más sencillo porque “solo” tienes que actualizar el servidor con el último merge y volver a desplegar tus servicios.

Servicios para configurar un servidor de CI/CD

Para configurar nuestro propio servidor de CI/CD tenemos varias opciones, podemos utilizar Jenkins o TeamCity, que es de los mismos desarrolladores del maravilloso Rider y se puede integrar todo en uno.

También tenemos la plataforma propia de Unity Cloud Build que va bien pero tiene algunas limitaciones que no tenemos con Jenkins o TeamCity, pero a cambio es bastante más sencillo de configurar y utilizar.

Y desde no hace mucho, un año o así, también lo podemos hacer con GitHub actions, o con GitLab pipeline si estás en gitlab. En nuestro caso lo haremos con GitHub pero el procedimiento es el mismo.

Además hacerlo con git hub actions es gratuito y muy fácil, en 10 minutos lo podemos tener funcionando, cosa que es impensable con Jenkins o TeamCity.

Lo que haremos será configurar estas acciones para que detecten cada vez que abrimos un pull request, entonces compilen el proyecto y ejecuten los tests del juego. Una vez hagamos merge queremos que genere una build para todas las plataformas que nos interesen con los últimos cambios.

Parece difícil pero por suerte ya ha habido gente que se ha currado la parte difícil, nosotros solo tenemos que consumir ese sistema y configurarlo a nuestro gusto.

¿Qué es una GitHub Action?

Sin entrar en mucho detalle, una acción está compuesta por el disparador de esa acción y por la lógica que ejecuta la acción. Todas las acciones lo que hacen es levantar una imagen de Docker que es un sistema operativo virtual con ciertos programas que nosotros configuremos, y aquí dentro ejecutamos lo que nos interese.

En este caso las Unity Actions que vamos a ver utilizan unas imágenes de Docker que que ya vienen con Unity instalado. Lo que harán las acciones es ejecutar Unity en modo linea de comandos, sin entorno gráfico, y lanzarle los comandos para compilar, ejecutar tests y hacer la build.

Github Actions para Unity

Vamos a partir de que tenemos ya un proyecto de Unity subido en GitHub y vamos añadir las Unity Actions para que compile el proyecto y pase los tests en los pull requests, y genere una build al hacer merge.

Lo primero sería pasarnos por la web de Unity Actions, documentarnos y comprobar que nuestra versión de Unity se encuentra dentro de la lista de versiones disponibles, en el caso de que no se encuentre podemos utilizar la más cercana.

Como lo que haremos será ejecutar Unity por línea de comandos, no os preocupéis porque esto será totalmente transparente para nosotros, lo primero que tendremos que hacer es obtener un archivo de licencia para Unity, nos vale tanto la free como la pro.

Si utilizas la versión pro el flujo que tendrás que seguir es otro, básicamente necesitas crear unas variables en la configuración de GitHub con tu usuario y password, aquí encontrarás las instrucciones detalladas.

Nosotros nos vamos a centrar en la versión free, para esto vamos a crear un Workflow que ejecute una serie de acciones para obtener un archivo de licencia que luego utilizaremos para generar la clave de licencia free.

Preparando GitHub para activar Unity

Lo primero será crear el Workflow para obtener el archivo de licencia, lo podemos crear en esta ruta: .github/workflows/activation.yml para esto vamos a nuestro repositorio y pulsamos sobre actions y luego set up a workflow.

ci unity

Esto nos abrirá un archivo de texto y tendremos que pegar el siguiente código:

name: Acquire activation file
on: [push]
jobs:
  activation:
    name: Request manual activation file 🔑
    runs-on: ubuntu-latest
    steps:
      # Request manual activation file
      - name: Request manual activation file
        id: getManualLicenseFile
        uses: webbertakken/unity-request-manual-activation-file@v1.1
        with:
          unityVersion: 2019.4.11f1
      # Upload artifact (Unity_v20XX.X.XXXX.alf)
      - name: Expose as artifact
        uses: actions/upload-artifact@v1
        with:
          name: ${{ steps.getManualLicenseFile.outputs.filePath }}
          path: ${{ steps.getManualLicenseFile.outputs.filePath }}

Vamos a tomarnos unos minutos para analizar que estamos haciendo:

La instrucción on nos dice cuándo se va a ejecutar este workflow, en este caso cada vez que hagamos un push a cualquier rama.

Los jobs son las acciones que ejecutará este workflow y nosotros tenemos 2, lo vemos dentro de steps, estas son webbertakken/unity-request-manual-activation-file@v1.1 que generará el archivo que estamos buscando y actions/upload-artifact@v1 que subirá el archivo a una sección llamada artefactos que veremos a continuación. Es importante que en la primera acción especifiquemos la versión sobre la que vamos a trabajar.

Para ejecutar este workflow simplemente tenemos que hacer un commit y push, y si volvemos a la sección de actions veremos que hay un workflow en ejecución. Cuando termine aparecerá un archivo en la sección de Artifacts.

git actions unity

Una vez descarguemos el fichero de licencia iremos a license.unity3d.com/manual y subiremos este archivo. Una vez subido seguimos los pasos y podremos descargar un segundo fichero que es la licencia en si.

Con este nuevo fichero lo que tenemos que hacer es abrirlo y copiar el contenido, entonces nos iremos a los settings de nuestro repositorio, a la sección de secrets, pegaremos ese contenido y como nombre le pondremos UNITY_LICENSE. Es necesario que sea ese nombre ya que es el mismo que utilizaremos en las acciones.

git hub actions unity

Una vez tengamos este archivo ya podemos eliminar el workflow que habíamos creados, su único cometido era generar este fichero.

Compilar y ejecutar los tests con cada pull request

Una vez hemos subido la licencia en la sección de secretos ya tendremos nuestro repositorio preparado para trabajar con las Unity Actions así que vamos a crear nuestro primer workflow.

Como antes volvemos a la sección de Actions y pulsamos sobre crear un nuevo workflow y pegamos el siguiente código:

name: Check tests

on:
  pull_request: {}

env:
  UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}

jobs:
  buildAndTestForSomePlatforms:
    name: Build for ${{ matrix.targetPlatform }} on version ${{ matrix.unityVersion }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        projectPath:
          - ./
        unityVersion:
          - 2019.4.11f1
        targetPlatform:
          - StandaloneOSX # Build a macOS standalone (Intel 64-bit).
          - StandaloneWindows64 # Build a Windows 64-bit standalone.
          - StandaloneLinux64 # Build a Linux 64-bit standalone.
    steps:
      - uses: actions/checkout@v2
        with:
          lfs: true
      - uses: actions/cache@v1.1.0
        with:
          path: ${{ matrix.projectPath }}/Library
          key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
          restore-keys: |
            Library-${{ matrix.projectPath }}-
            Library-
      - uses: webbertakken/unity-test-runner@v1.3
        id: testRunner
        with:
          projectPath: ${{ matrix.projectPath }}
          unityVersion: ${{ matrix.unityVersion }}
      - uses: actions/upload-artifact@v1
        with:
          name: Test results (all modes)
          path: ${{ steps.testRunner.outputs.artifactsPath }}

Esta vez el trigger será on: pull_request y hemos añadido una nueva sección con las variables de entorno, env donde hemos registrado la variable de licencia.

Dentro de los jobs hemos creado una strategy con distintas variables, a groso modo, este workflow se ejecutará tantas veces como la combinación de variables declarada en esta sección.

Lo que nos interesa de aquí es configurar la ruta de nuestro proyecto, en mi caso el proyecto está en la raíz y por lo tanto la ruta es ./, si vosotros lo tenéis en una subcarpeta lo tendréis que indicar aquí, por ejemplo ./myProyecto.

También tendremos que configurar la versión de Unity que queremos utilizar, tiene que coincidir con la versión que utilizamos para generar la licencia, y configuraremos todas las plataformas para las que queremos que se ejecute el workflow.

Recuerda que si estás trabajando en Android y iOS primero tendrás que configurar el proyecto, yo te recomiendo que primero hagas una build local para comprobar que todo está correcto.

Lo siguiente son los steps:

  • actions/checkout@v2, hará checkout al commit donde haya saltado el trigger.
  • actions/cache@v1.1.0, esta acción se encargará restaurar la carpeta de Library cada vez que se ejecute el workflow y de guardarla cuando termine, así ahorraremos tiempo.
  • webbertakken/unity-test-runner@v1.3, esta acción ejecutará los tests.
  • actions/upload-artifact@v1, esta acción ya la utilizamos con la licencia y lo que hará será subir como un artefacto el resultado de los tests.

Para probar que todo funciona solo tendremos que abrir un pull request y se hará la magia.

unity ci gratuito

Si todo va bien aparecerá en verde, y si hay algún problema aparecerá en rojo.

Ahora lo que podemos hacer es configurar nuestro repositorio para que no nos deje hacer merge si no está todo en verde, para eso vamos a Settings, Branches y añadimos una nueva regla de protección sobre la rama que queramos.

unity github

Tener en cuenta que las acciones no aparecerán hasta que no se ejecuten por primera vez.

Generar builds de forma automática

Ya casi tenemos nuestro servidor de integración continua funcionando a tope, solo nos falta que genere las builds con cada merge que hagamos. Para eso vamos a crear el siguiente workflow:

name: Build

on:
  push: { branches: [main] }

env:
  UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}

jobs:
  buildAndTestForSomePlatforms:
    name: Build for ${{ matrix.targetPlatform }} on version ${{ matrix.unityVersion }}
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        projectPath:
          - ./
        unityVersion:
          - 2019.4.11f1
        targetPlatform:
          - StandaloneOSX # Build a macOS standalone (Intel 64-bit).
          - StandaloneWindows64 # Build a Windows 64-bit standalone.
          - StandaloneLinux64 # Build a Linux 64-bit standalone.
    steps:
      - uses: actions/checkout@v2
        with:
          lfs: true
      - uses: actions/cache@v1.1.0
        with:
          path: ${{ matrix.projectPath }}/Library
          key: Library-${{ matrix.projectPath }}-${{ matrix.targetPlatform }}
          restore-keys: |
            Library-${{ matrix.projectPath }}-
            Library-
      - uses: webbertakken/unity-builder@v0.10
        with:
          projectPath: ${{ matrix.projectPath }}
          unityVersion: ${{ matrix.unityVersion }}
          targetPlatform: ${{ matrix.targetPlatform }}
      - uses: actions/upload-artifact@v1
        with:
          name: Build
          path: build

La única diferencia con el workflow anterior es que hemos quitado los tests y ejecutaremos la acción webbertakken/unity-builder@v0.10 la cual generará la build y con actions/upload-artifact@v1 la subiremos a Artifacts.

También hemos cambiado el trigger para que sea on: push: { branches: [main] } en nuestro caso queremos que con cada push a la rama main se ejecute este workflow, pero aquí podemos indicar cualquier rama.

Cuando esta acción termine veremos un .zip con la build de todas las plataformas que hemos indicado.

unity build ci

Conclusión

Hemos visto como con 2 workflows podemos tener nuestro servidor de integración continua (CI) totalmente listo, y lo mejor de todo es que nos protegerá de que hagamos un merge sin pasar los tests y compilar el proyecto.

Además con cada merge publicará una build con los últimos cambios que todo el equipo podrá utilizar, ya no tendremos que depender del desarrollador para generar una build ni andar preguntando cuál es la última o donde la puedo descargar.

En este enlace te dejo el repositorio que hemos utilizado como ejemplo en este post para que lo tengas de referencia.

Otras entradas

Resumen
➤ Cómo aumentar el rendimiento de tu equipo en Unity
Nombre del artículo
➤ Cómo aumentar el rendimiento de tu equipo en Unity
Descripción
➤ Con GitHub actions podrás generar builds de forma automática para tu proyecto en UNITY y de forma TOTALMENTE GRATUITA 🤯.
Autor
Publisher Name
The Power Ups - Learning
Publisher Logo

2 pensamientos sobre “Cómo aumentar el rendimiento de tu equipo en Unity”

  1. Hola, nunca he trabajado con Github, y la verdad es que no me aclaro bien. ¿podrias explicarlo paso a paso? Me resulta muy interesante la idea de este articulo, pero para mi, muy complicado. Gracias.

    1. ¡Hola! Si has trabajado con Bitbucket, GitLab o similar, GitHub es lo mismo que cualquier servicio de Git. La idea del artículo no es explicar cómo funciona git o GitHub, para eso ya hay un montón de contenido por internet. Si quieres ver como configurar las acciones paso a paso tenemos un vídeo en el canal, te dejo el enlace: https://youtu.be/u5LGtbsodpE
      ¡Un saludo!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *