Praxsuite

Implementación del SDK de Unity

Mirko Franichevic · 27 de agosto de 2026

¿Qué Vamos a Hacer?

Vas a conectar un juego Unity con Praxsuite: primero autenticación, después una tabla pequeña de progreso del jugador, y finalmente un Gateway Endpoint del servidor. La meta todavía no es construir un juego completo. La meta es ver datos reales moverse desde Unity hacia Praxsuite y volver de una forma segura para seguir construyendo.

Al terminar esta guía sabrás:

  • Qué es un workspace de Praxsuite y dónde encaja Unity

  • Cómo instalar el paquete del SDK (Software Development Kit) de Praxsuite

  • Cómo configurar el SDK con un Workspace ID

  • Cómo iniciar sesión con Prax.Auth

  • Cómo leer y escribir filas de una Table con Prax.Data

  • Cómo llamar lógica del servidor con Prax.Endpoints

Required level: Debes poder crear scripts y GameObjects en Unity. No necesitas experiencia previa con APIs o backends.


¿Qué es Praxsuite?

Piensa en Praxsuite como un backend en la nube con el que tu juego habla por HTTPS. Un Workspace es la carpeta grande que contiene tus Tables, usuarios, endpoints de Gateway, Automations, archivos y configuración. Una Table es donde viven filas de datos. Un Endpoint es una puerta pública hacia una Automation, que es lógica del servidor que el jugador no puede inspeccionar ni reescribir.

Esa separación es la idea importante para juegos. Unity es excelente para controles, animación y presentación. Praxsuite es donde pones los datos y decisiones que un cliente modificado no debe poder falsificar.

What is a Gateway? El Gateway es la puerta de entrada del workspace. Recibe requests, revisa credenciales, aplica scopes y límites de tasa, y dirige la llamada a auth, data, files o una Automation.


Requisitos Previos

Requisito

Descripción

Unity 2021.3 o superior

El paquete SDK declara Unity 2021.3 como versión mínima

Paquete SDK de Praxsuite

Instalado como com.tesseractsoftwares.praxsuite

Workspace de Praxsuite

Crea uno en el portal antes de empezar

Table PlayerSaves

Columnas: Owner como Enduser, Level como Number, Coins como Number

Rol de jugador

Con scope a PlayerSaves, filtro __SELF__ y default {{claim:sub}} en Owner

End-user de prueba

Email y contraseña que puedas usar desde Play mode

Important: `SELF` y `{{claim:sub}}` hacen trabajos distintos. El row filter limita lecturas y updates. El default estampa propiedad al insertar. Configura sólo uno y el primer guardado suele funcionar de forma confusa: escribe, y luego desaparece de la vista del propio jugador.


Cómo Obtener tus Credenciales

Unity necesita la ubicación del workspace, no un secreto. El SDK puede obtener la publishable key desde /auth/config, así que el valor obligatorio que debes pegar es el Workspace ID.

Tu Workspace ID

Abre tu workspace en el portal y copia el UUID (Universally Unique Identifier) que viene después de /workspace/:

https://portal.praxsuite.com/workspace/ffd80539-a1e2-4a9e-8b33-f716bf690281
                                       esta parte es el Workspace ID

Tu Key: publishable vs secret

Praxsuite tiene dos familias de keys. No son intercambiables.

Key

Prefijo

Dónde puede vivir

Publishable

pk_live_

Código de cliente. Identifica el workspace y puede obtenerse públicamente

Secret

sk_live_

Sólo servidor confiable. Nunca dentro de un build Unity para jugadores

Para este SDK, empieza dejando vacía la publishable key. El settings asset tiene un campo opcional para ella, pero el auto-discovery deja un valor menos dentro del proyecto Unity.

Golden rule: Nunca publiques una secret key dentro de un cliente Unity. El build guard del SDK escanea builds de jugador y falla cuando encuentra un valor real `sklive` bajo `Assets/` o `ProjectSettings`.

API_KEYS.png

Step 1 - Instalar el SDK

Repositorio: https://github.com/TesseractSoftwares/Praxsuite-SDK-Unity

Abre Package Manager de Unity y elige Add package from git URL. Pega:

https://github.com/TesseractSoftwares/Praxsuite-SDK-Unity.git

Unity registra la dependencia en Packages/manifest.json:

{
  "dependencies": {
    "com.tesseractsoftwares.praxsuite": "https://github.com/TesseractSoftwares/Praxsuite-SDK-Unity.git"
  }
}

Después de resolver paquetes, un script bajo Assets/ debe compilar con este using:

using Praxsuite;
Captura de pantalla 2026-08-27 111649.png

Step 2 - Crear el Cliente

En la mayoría de proyectos no construyes un cliente manualmente. Creas un settings asset y el punto de entrada estático Prax lo lee al primer uso.

En Unity, haz clic en Praxsuite -> Create Settings Asset. Esto crea:

Assets/
  Resources/
    PraxsuiteSettings.asset

Abre Project Settings -> Praxsuite y pega tu Workspace ID. Deja Publishable Key vacío salvo que necesites usar una publishable key específica.

Al inicio, prepara el SDK detrás de una pantalla de carga:

using Praxsuite;
using UnityEngine;

public class PraxBoot : MonoBehaviour
{
    private async void Start()
    {
        var workspace = await Prax.InitializeAsync();
        Debug.Log("Connected to " + workspace.WorkspaceName);
    }
}

Si el Workspace ID o el host están mal, esto falla temprano en vez de fallar después durante el login.

¿Por qué un settings asset y no un cliente hard-coded?

Un settings asset es visible en el Inspector, se incluye en builds mediante Resources y lo revisa el build guard del SDK. Valores hard-coded quedan escondidos en scripts y son más fáciles de copiar a la escena o build target equivocado.


Step 3 - Iniciar Sesión

La autenticación de Praxsuite devuelve una sesión de jugador. Esa sesión incluye un JSON Web Token (JWT), y el SDK lo agrega automáticamente a llamadas de Data y Endpoints.

Crea un script con credenciales de prueba serializadas:

using Praxsuite;
using UnityEngine;

public class PraxLoginProbe : MonoBehaviour
{
    [SerializeField] private string email = "player@example.com";
    [SerializeField] private string password = "";

    private async void Start()
    {
        try
        {
            var result = await Prax.Auth.LoginAsync(email, password);

            if (result.RequiresEmailConfirmation)
            {
                Debug.LogWarning("Confirm your email address before signing in.");
                return;
            }

            Debug.Log("Signed in as " + Prax.Auth.CurrentUser.DisplayName);
        }
        catch (PraxException ex) when (ex.IsAuthFailure)
        {
            Debug.LogWarning("Wrong email or password.");
        }
    }
}

Ejecuta la escena. La Console debe imprimir el display name del jugador, o una advertencia clara si las credenciales están mal.

¿Por qué el SDK no confía en un parámetro player id?

Un parámetro viene del cliente, y el jugador controla el cliente. La identidad confiable es el claim subject del JWT que Praxsuite emitió después del login. Por eso los row filters y las Automations deben leer al caller desde la sesión, no desde un campo de texto.


Step 4 - Leer y Escribir Datos

Crea una Table PlayerSaves en Praxsuite con:

Columna

Tipo

Notas

Owner

Enduser

Tiene default value template {{claim:sub}}

Level

Number

Progreso del jugador

Coins

Number

Moneda del jugador para esta prueba simple

Ahora carga la fila del jugador. Observa que no hay where Owner = me en Unity. El role scope aplica eso en el servidor.

using System.Collections.Generic;
using System.Threading.Tasks;
using Praxsuite;
using UnityEngine;

public class PraxSaveProbe : MonoBehaviour
{
    private const string SaveTable = "PlayerSaves";

    public async Task<PraxRow> LoadOrCreateSaveAsync()
    {
        var existing = await Prax.Data.From(SaveTable).FirstAsync();
        if (existing != null)
            return existing;

        var created = await Prax.Data.InsertAsync(SaveTable, new Dictionary<string, object>
        {
            { "Level", 1 },
            { "Coins", 0 }
        });

        return created.Row;
    }

    public async Task SaveAsync(string rowId, int level, int coins)
    {
        await Prax.Data.UpdateByIdAsync(SaveTable, rowId, new Dictionary<string, object>
        {
            { "Level", level },
            { "Coins", coins }
        });

        Debug.Log("Saved level " + level + " with " + coins + " coins.");
    }
}

Lee valores con getters tipados:

var save = await LoadOrCreateSaveAsync();
Debug.Log("Level " + save.GetInt("Level") + ", coins " + save.GetInt("Coins"));

La columna Owner falta en el insert a propósito. Praxsuite la completa desde la sesión verificada.


Step 5 - Llamar un Gateway Endpoint

Las escrituras directas a Table están bien para campos inofensivos del propio jugador. Cualquier cosa valiosa debe pasar por un Endpoint porque una Automation puede validarla en el servidor.

Crea un endpoint Sync llamado claim-daily-reward cuya Automation decida si el jugador puede recibir recompensa, y llámalo desde Unity:

using System.Collections.Generic;
using Praxsuite;
using UnityEngine;

public class PraxRewardProbe : MonoBehaviour
{
    public async void ClaimDailyReward()
    {
        try
        {
            var response = await Prax.Endpoints.CallAsync("claim-daily-reward",
                new Dictionary<string, object>
                {
                    { "clientTime", System.DateTimeOffset.UtcNow.ToString("O") }
                });

            var row = PraxRowReader.ReadRow(response);
            Debug.Log("Reward accepted: " + row.GetBool("accepted", false));
        }
        catch (PraxException ex)
        {
            Debug.LogWarning("Reward failed: " + ex.Message);
        }
    }
}

El cliente envía contexto. La Automation decide. Ese es el hábito correcto antes de construir monedas, inventarios, puntajes rankeados o lógica competitiva.

Captura de pantalla 2026-08-28 092512.png

Ejemplo Completo

Este MonoBehaviour inicia sesión, carga o crea un save, lo incrementa y llama un endpoint. Asume que el settings asset existe y que completaste la configuración del portal de las secciones anteriores.

using System.Collections.Generic;
using System.Threading.Tasks;
using Praxsuite;
using UnityEngine;

public class PraxImplementationExample : MonoBehaviour
{
    [SerializeField] private string email = "player@example.com";
    [SerializeField] private string password = "";

    private const string SaveTable = "PlayerSaves";

    private async void Start()
    {
        try
        {
            var workspace = await Prax.InitializeAsync();
            Debug.Log("Connected to " + workspace.WorkspaceName);

            if (!Prax.Auth.IsSignedIn)
            {
                var login = await Prax.Auth.LoginAsync(email, password);
                if (!login.IsSignedIn || login.RequiresEmailConfirmation)
                {
                    Debug.LogWarning("The player is not ready to play.");
                    return;
                }
            }

            var save = await LoadOrCreateSaveAsync();
            var nextLevel = save.GetInt("Level") + 1;
            var nextCoins = save.GetInt("Coins") + 25;

            await Prax.Data.UpdateByIdAsync(SaveTable, save.Id, new Dictionary<string, object>
            {
                { "Level", nextLevel },
                { "Coins", nextCoins }
            });

            var reward = await Prax.Endpoints.CallAsync("claim-daily-reward");
            Debug.Log("Endpoint returned " + reward.Count + " fields.");
        }
        catch (PraxException ex)
        {
            Debug.LogWarning(ex.ToString());
        }
    }

    private static async Task<PraxRow> LoadOrCreateSaveAsync()
    {
        var save = await Prax.Data.From(SaveTable).FirstAsync();
        if (save != null)
            return save;

        var created = await Prax.Data.InsertAsync(SaveTable, new Dictionary<string, object>
        {
            { "Level", 1 },
            { "Coins", 0 }
        });

        return created.Row;
    }
}

Presiona Play. Una ejecución correcta conecta, inicia sesión, crea o lee el save del jugador, lo actualiza y llega al endpoint.

Captura de pantalla 2026-08-31 003323.png

Errores Comunes y Cómo Evitarlos

Error

Causa

Solución

PraxsuiteOptions.WorkspaceId is required.

No existe settings asset, o WorkspaceId está vacío

Crea Assets/Resources/PraxsuiteSettings.asset desde el menú Praxsuite y pega el UUID del workspace

PraxsuiteOptions.WorkspaceId is not a valid GUID: ...

El valor copiado incluye espacios, texto de URL u otro valor que no es UUID

Copia sólo el UUID después de /workspace/

An endpoint slug is required.

Prax.Endpoints.CallAsync recibió un string vacío

Revisa el slug o id del endpoint antes de llamar

UpdateAsync requires at least one filter. An update with no WHERE clause would rewrite every row...

Usaste UpdateAsync sin filtros

Usa UpdateByIdAsync para una fila o pasa un PraxFilter real

DeleteAsync requires at least one filter. A delete with no WHERE clause would empty the table...

Intentaste un delete sin alcance

Borra por id o agrega filtros deliberadamente

ChangePasswordAsync needs a signed-in player. Use ForgotPasswordAsync for a player who cannot sign in.

Llamaste un método de auth que requiere sesión antes del login

Bloquea acciones de cuenta hasta que Prax.Auth.IsSignedIn sea true

The gateway did not return a total count for this query...

CountAsync no recibió metadata total, a menudo porque agregaciones no están habilitadas en el scope

Habilita acceso de aggregation/count o usa Aggregate("count", "*", "n") donde esté permitido


Consejos Para Producción

  • Publica sólo una publishable key, o déjala vacía y deja que el SDK la obtenga desde /auth/config.

  • Mantén VerboseLogging apagado en builds de release porque los bodies pueden incluir datos del jugador.

  • Usa Prax.Endpoints para recompensas, compras, envío de puntajes y cualquier cosa que un cliente modificado quiera falsificar.

  • Usa UpdateByIdAsync o UpdateAsync con filtros; las escrituras sin alcance se rechazan por una buena razón.

  • Prueba un build real para que el build guard de Praxsuite bloquee secret keys y hosts remotos inseguros.

  • Prefiere CancellationToken para flujos de UI que pueden cerrarse antes de que vuelva una request.


Próximos Pasos

  • Importa el sample Quick Start del SDK desde Package Manager y compáralo con tu script.

  • Agrega un panel de login real en vez de credenciales serializadas de prueba.

  • Construye un leaderboard pequeño siguiendo el patrón del sample del SDK.

  • Mueve recompensas de moneda detrás de un endpoint Sync antes de agregar inventario.

  • Continúa con el Unity Minesweeper Use Case cuando esta primera integración funcione.

Ahora Unity ya habla con Praxsuite mediante auth, data y lógica server-side. Esa es la base sobre la que se sostiene el juego completo.