William Gaonarc'h

Développeur Fullstack

Intégration complète de Supabase dans Unity WebGL avec Nuxt

Dans mon application RPGFitness.fr, j’ai intégré un jeu Unity WebGL directement dans une application Nuxt + Capacitor, tout en connectant le système de progression du joueur à Supabase.

Ce setup m’a permis de :

  • gérer l’authentification du joueur via Supabase Auth,
  • charger les stats du personnage depuis Supabase,
  • envoyer ces données à Unity pour les combats,
  • récupérer la progression (chapitres terminés) depuis Unity,
  • maintenir une communication temps réel Nuxt → Unity → Nuxt via postMessage.

C’est une architecture rare, mais extrêmement puissante.


🏗️ Architecture générale

Supabase ←→ Nuxt (Capacitor mobile) ←(postMessage)→ Unity WebGL

yaml Copier le code

  • Nuxt gère l’authentification + les données du joueur.
  • Unity WebGL gère le combat, les chapitres, la progression RPG.
  • postMessage synchronise les deux environnements.

🔐 1. Authentification via Supabase (côté Nuxt)

Unity WebGL ne gère pas les secure cookies, ni Supabase Auth directement.
Donc Nuxt login → Unity reçoit juste les données nécessaires.

Après connexion, Nuxt charge :

  • inventaire,
  • totaux (dégâts / PV / armure),
  • personnage sélectionné,
  • niveau de chapitre.

Tout ceci est encapsulé dans une classe :

const Perso = new Personnage(account.uid, supabase); await Perso.getInventaire(); await Perso.recupererDetailsInventaire(); await Perso.calculerTotaux(); C’est ensuite Unity qui demande ces données.

🔁 2. Communication Unity → Nuxt avec postMessage Dans le WebGL, Unity appelle une fonction JS exportée :

#if UNITY_WEBGL && !UNITY_EDITOR DllImport("__Internal") private static extern void RequestCharacterData(); #endif Au lancement du jeu :

RequestCharacterData(); Ce qui déclenche dans le fichier HTML WebGL :

window.parent.postMessage({ type: "GET_CHARACTER_DATA", payload: { gameObjectName, methodName } }, "*"); Nuxt reçoit ce message :

window.addEventListener("message", async (event) => { if (event.data.type === "GET_CHARACTER_DATA") { // chargement du personnage depuis Supabase... iframe.contentWindow.postMessage({ type: "CHARACTER_DATA", payload: { gameObjectName, methodName, data: JSON.stringify(characterData) } }, "*"); } }); Nuxt renvoie alors les données RPG à Unity.

🎮 3. Réception des données dans Unity Unity reçoit via SendMessage :

public void ReceiveMessage(string message) { CharacterData character = JsonUtility.FromJson(message);

GameManager.Instance.playerData = character;

// Chargement du chapitre correspondant
ChapterData chapter = chapterDataList.chapters
    .Find(c => c.levelChapitre == character.levelChapitre);

} Unity se configure automatiquement avec les stats du joueur stockées dans Supabase.

📤 4. Envoyer la progression à Supabase (Unity → Nuxt) Lorsqu’un chapitre est terminé :

window.parent.postMessage({ type: "FROM_UNITY", payload: chapterLevel }, "*"); Nuxt reçoit :

account.level_chapitre = chapterLevel + 1;

const { updateUser } = useProfiles(); await updateUser(account.uid, { level_chapitre: chapterLevel + 1 }); Le niveau est mis à jour dans Supabase.

📱 5. Gestion du viewport sur mobile (Capacitor) Un point souvent oublié : Unity WebGL dans une app mobile Capacitor casse le viewport mobile.

J’ai donc ajouté un système avancé qui :

détecte iOS/Android,

compense la hauteur du menu custom,

surveille visualViewport,

recalcule dynamiquement la hauteur utilisable.

Extrait :

function updateVh() { containerHeight.value = window.innerHeight - CUSTOM_MENU_HEIGHT; document.documentElement.style.setProperty( "--real-vh", ${containerHeight.value * 0.01}px ); } Ce fix améliore énormément l’expérience mobile.

🚧 6. Limitations rencontrées & solutions ❌ Supabase JS non supporté dans WebGL → Solution : Nuxt fait les requêtes, Unity reçoit juste les données.

❌ SendMessage non fiable avant initialisation Unity → Solution : Attendre unityInstance :

if(window.unityInstance) { window.unityInstance.SendMessage(...); } ❌ Viewport mobile instable → Solution : Système basé sur visualViewport + recalcul dynamique.

❌ JsonUtility limité → Solution : Structures de données simples et typées.

🏆 Résultat final Grâce à cette architecture :

Le joueur est authentifié via Supabase.

Ses stats sont chargées depuis Nuxt.

Unity récupère et applique les données automatiquement.

Unity renvoie la progression à Supabase.

Le tout fonctionne sur Web, Android, et iOS.

Un vrai système RPG temps réel complet, basé sur une stack moderne.

🔗 Voir aussi 👉 Projet complet : https://rpgfitness.fr