Pang Pang Club

Tuto Unity : Intégrer avec succès son jeu dans une page web

le 07 mai, 2020

Publier ses créations unity sous la forme d'un HTML peut présenter de nombreux avantages. En plus d'être dans la lignée des jeux flash, vous permettez aux joueur⋅euse⋅s de jouer très facilement à votre jeu depuis navigateur. Il peut être lourd de passer par un téléchargement, attendre, décompresser le dossier, etc.

Seulement, que vois-je?! Quel est cette affreuse chose, cette abomination ? Que fait ce footer répugnant de banalité sous mon sublimifique jeu ?

Voici donc la raison d'être de ce tutoriel : apprendre à retirer le footer d'un jeu Unity WebGL.

Étape 1 : Exporter le projet

Tout d'abord, vous aurez besoin d'exporter votre projet Unity en un jeu HTML. Pour cela, cliquez dans File -> Build Settings… (ou faites Ctrl + Shift + B). Sélectionnez "WebGL" puis cliquez sur "Build".

Note : WebGL (Web Graphics Library) est une API JavaScript pour produire des graphismes 2D et 3D interactifs. En gros, c'est un ensemble d'outils spécialisés qui sert à faire des rendus sur une page HTML.

Sélectionnez un dossier dans lequel Unity exportera le projet, validez, attendez, et votre gâteau est prêt ! Mais ce n'est pas fini. C'est maintenant que les choses vont commencer à se corser.

Étape 2 : Modifier le HTML

Si vous ouvrez votre dossier qui contient le projet, vous devriez voir trois choses: un dossier Build, un dossier TemplateData, et un fichier index.html.

Le dossier TemplateData contient des icônes, images, une feuille de CSS et un script JS. C'est pour la page de chargement du jeu. Le dossier Build est un peut le cœur du jeu, c'est la no-touch zone. Le seul fichier qui pourrait nous y intéresser est le fichier (nom de projet).json. Le fichier index.html est, en quelque sorte, le réceptacle de votre jeu. Wow, sexy.

Note : Lorsque vous publiez un jeu HTML sur itch.io, ou sur n'importe quelle autre plateforme, c'est TOUJOURS le fichier index.html qui sera cherché et lancé. Ne modifiez donc pas son nom, et ne le rangez pas dans un sous-dossier.

Avant toute chose, dupliquez le fichier index.html et renommez le duplicata backup.html, ou pastouche.html, comme vous voulez. C'est une sécurité, au cas où on foire tout.

Maintenant, ouvrez le fichier index.html avec votre éditeur de code favori. En principe, vous devriez en avoir un, sinon je sais pas comment vous avez fait votre jeu Unity. Au pire, vous pouvez l'ouvrir avec votre bloc-note pourri.

Vous devriez avoir ceci, ou quelque chose de fortement semblable :

<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Unity WebGL Player | TOASTEUR</title>
    <link rel="shortcut icon" href="TemplateData/favicon.ico">
    <link rel="stylesheet" href="TemplateData/style.css">
    <script src="TemplateData/UnityProgress.js"></script>
    <script src="Build/UnityLoader.js"></script>
    <script>
      var unityInstance = UnityLoader.instantiate("unityContainer", "Build/fumee-des-miettes V5.json", {onProgress: UnityProgress});
    </script>
  </head>
  <body>
    <div class="webgl-content">
      <div id="unityContainer" style="width: 960px; height: 600px"></div>
      <div class="footer">
        <div class="webgl-logo"></div>
        <div class="fullscreen" onclick="unityInstance.SetFullscreen(1)"></div>
        <div class="title">TOASTEUR</div>
      </div>
    </div>
  </body>
</html>

Pour celleux qui n'ont jamais vu de HTML de leur vie, une très rapide introduction bâclée : l'HTML est un langage descriptif utilisé pour le web. C'est ce qui décrit les éléments qu'il y a sur la page, avec ce qu'on appelle des balises, ou des tags. C'est le HTML qui dit: "alors dans ma page, j'ai un bloc de texte, une image et un bloc de texte, et un bouton, tout ça contenu dans une grande page elle-même contenue dans une grande boîte…". Si vous souhaitez vous y plonger un peu, une excellente et solide référence pour débuter : w3school.

Première étape, vous pouvez changer ce qui se trouve dans la balise <title>, qui se trouve ligne 6. Cette balise décrit ce qui sera affiché comme titre dans l'onglet du navigateur :

Vous n'avez peut-être pas envie que l'onglet affiche "Unity WebGL Player | monprojétrobo", mais plutôt "~Mon projet sublimifique~", n'est-ce pas ? Rien de bien compliqué, il suffit de remplacer :

<title>Unity WebGL Player | TOASTEUR</title>

par :

<title>~Mon projet sublimifique~</title>

Ensuite, passons au footer moche. Le footer moche se trouve là, devant vos yeux, lignes 18 à 22 :

<div class="footer">
    <div class="webgl-logo"></div>
    <div class="fullscreen" onclick="unityInstance.SetFullscreen(1)"></div>
    <div class="title">TOASTEUR</div>
</div>

En commentant des lignes, on peut les rendre inactives. Pour commenter une ligne, il suffit de mettre <!-- au début et --> à la fin de cette ligne.

Note : Les commentaires, dans un code, sont des messages ou du code qui ne seront jamais lus par la machine, et donc pas interprétés. Commenter une ligne revient à la rendre inexistante, mais sans l'effacer. Croyez-moi, c'est essentiel.

Nous pouvons commencer par commenter le logo WebGL moche ainsi que le titre du jeu comme ci-dessous.

<div class="footer">
    <!-- <div class="webgl-logo"></div> -->
    <div class="fullscreen" onclick="unityInstance.SetFullscreen(1)"></div>
    <!-- <div class="title">TOASTEUR</div> -->
</div>

pour passer de ça…

à ça :

Pas terrible. Il reste ce foutu bouton fullscreen qui est bleu, tout moche. Vous avez trois possibilités. Soit vous laissez la chose en l'état (moyennement satisfaisant), soit vous retirez tout le footer (mais au revoir le full screen), soit vous faites votre propre bouton (un peu plus difficile, mais ça en vaut la peine).

Retirer tout le footer :

Il suffit de commenter l'intégralité du footer dans le code. voici ce que ça donne :

<!-- <div class="footer">
    <div class="webgl-logo"></div>
    <div class="fullscreen" onclick="unityInstance.SetFullscreen(1)"></div>
    <div class="title">TOASTEUR</div>
</div> -->

Et, en image, le footer a complètement disparu. Miracle !

Vous pouvez vous contenter de cela, car vous aurez atteint le but principal, à savoir dégager le footer moche par défaut. Seulement, vous ne pourrez plus jouer en plein écran. Cela peut être gênant, ou pas. Si vous vous dites qu'il suffit de cocher "Fullscreen button — Add a button to the bottom right corner of your embed to make it fullscreen" sur itch.io, vous allez être déçu⋅e. Voici ce que vous obtiendrez.

beurk

Étape 3 (avancé) : Faire son propre bouton plein écran

Cette étape est pour les vrai⋅e⋅s guerrier⋅ère⋅s, les pourfendeu⋅r⋅ses de dragons, les braves qui ne craignent ni flamme ni tempête, qui ne reculent devant aucun obstacle pour venir au secours de leur jeu bien-aimé. Non, je déconne. On va juste faire du HTML. Seulement, cette partie peut s'avérer un peu plus ardue pour les personnes qui n'ont aucune base en HTML.

Pour obtenir un véritable plein écran pour votre jeu, vous aurez besoin d'employer du JavaScript. Pas d'inquiétude toutefois, la fonction dont nous avons besoin est déjà toute prête, nous aurons juste à la déclencher. Nous allons nous pencher sur le bouton qui existait déjà dans le footer :

<div class="fullscreen" onclick="unityInstance.SetFullscreen(1)"></div>

J'attire votre attention sur l'attribut onclick de cette balise. À l'intérieur, il s'agit d'une commande JavaScript (js) : unityInstance.SetFullscreen(1). Il se peut que ce soit légèrement différent pour vous, et que vous ayez gameInstance.SetFullscreen(1), par exemple. Soyez particulièrement vigilant⋅e sur ce détail important. Cette commande est celle qui affiche le jeu en plein écran.

Nous allons écrire notre propre balise. Voici ce que je vous propose d'écrire :

<div class="fsButton" title="Fullscreen" onclick="unityInstance.SetFullscreen(1)"></div>

L'attribut class="fsButton" va nous permettre d'identifier le bouton pour, par exemple, changer son apparence (via CSS). Vous pouvez choisir le nom que vous voulez, comme class="mon-bouton-trop-classe". L'attribut title="Fullscreen", quant à lui, permettra d'afficher "Fullscreen" au survol de la souris sur le bouton. Et, le plus important, l'attribut onclick. Un simple copier/coller depuis l'ancien bouton du footer suffit. Si vous aviez gameInstance.SetFullscreen(1), alors c'est bien ça que vous devez mettre dans l'attribut onclick !

Ce bouton est à placer sous le <div id="unityContainer" style="width: 960px; height: 600px"></div> (ligne 36) de votre HTML. Comme ceci :

<body style="margin: 0;">
    <div class="webgl-content">
      <div id="unityContainer" style="width: 960px; height: 600px"></div>
      <div class="fsButton" title="Fullscreen" onclick="unityInstance.SetFullscreen(1)"></div>
      <!-- <div class="footer">
        <div class="webgl-logo"></div>
        <div class="fullscreen" onclick="unityInstance.SetFullscreen(1)"></div>
        <div class="title">TOASTEUR</div>
      </div> -->
    </div>
</body>

Mais cela ne suffit pas. Votre boutton est vide. Je vous propose de mettre une image à l'intérieur via la balise img. J'ai chopé l'icône de itch.io pour le fullscreen, si vous voulez.

Note : vous pouvez modifier ce svg en l'ouvrant dans votre éditeur de code, pour par exemple avoir une autre couleur que ce rose. Vous verrez que c'est pareil que du html. Pour en savoir plus sur le svg : introduction au svg sur w3school.

Mettez l'image de votre choix (je vous recommande vivement le svg ci-dessus quand même) dans le dossier qui contient votre projet. Par exemple, vous pouvez le mettre dans le sous-dossier TemplateData, ou mieux : créer votre propre sous-dossier et y ranger votre image. Pour ma part, j'ai créé un sous-dossier qui s'appelle VelData (pour "Velvet Data", très original je sais), à l'intérieur duquel j'ai rangé l'image enlarge.svg. Ensuite, on modifie l'HTML :

<div class="fsButton" title="Fullscreen" onclick="unityInstance.SetFullscreen(1)">
    <img src="VelData/enlarge.svg" width="60" height="60"> </img>
</div>

Note : La balise <img> doit se trouver à l'intérieur du <div class="fsButton">, c'est-à-dire que la balise fermante</div> se trouve après </img>.

Cette balise <img> contient trois informations. La source de l'image, sa largeur et sa hauteur à l'affichage. Vous devez spécifier le chemin exact pour la source (src), en fonction de là où votre image est rangée. Mon image étant rangée dans le sous-dossier VelData, et portant le nom de enlarge.svg, mon chemin est donc VelData/enlarge.svg. La hauteur et la largeur sont exprimées par les attributs height et width, et ce en pixels. Le bouton fullscreen de itch.io est reglé à 30px. J'ai mis celui-ci à 60px, le choix vous revient.

Plus d'informations sur W3school.

Voici ce que j'obtiens :

Si je clique dessus, j'entre bien en plein écran, et c'est beau. En mode plein écran, le bouton n'apparaît plus. Parfait ! Seulement, je ne veux pas que mon bouton reste collé en bas comme une chausette. On va devoir écrire du CSS.

Étape 4 (avancée) : styler son beau bouton

Qu'est-ce que ça veut dire, "styler son bouton" ? Si vous êtes déjà familier⋅ère avec le CSS, vous pouvez passer à la suite. Tout à l'heure, je vous ai expliqué que le HTML était un langage qui décrivait le contenu d'une page web : un menu, dans lequel j'ai des liens, et puis une grande page avec du texte dedans, etc. Seulement, l'HTML tout seul ne décrit pas l'apparence de ces éléments : la couleur de fond, la taille, la police de caractère, le positionnement, etc. L'apparence des éléments d'une page web est gérée par le CSS.

« Cascading Style Sheets (CSS) est un langage de feuille de style utilisé pour décrire la présentation d'un document écrit en HTML ou en XML (on inclut ici les langages basés sur XML comme SVG ou XHTML). CSS décrit la façon dont les éléments doivent être affichés à l'écran, sur du papier, en vocalisation, ou sur d'autres supports. » ( MDN )

Quand on dit "styler un bouton (ou autre chose)", on parle donc d'attribuer des éléments de CSS à ce bouton, pour en modifier l'apparence.

Pour écrire une feuille de style, c'est assez simple. Vous n'avez pas besoin de l'écrire séparément, vous pouvez l'inclure directement dans votre HTML. Il vous suffit d'ouvrir une balise <style type="text/css"> dans le <head> de votre HTML.

<head>
    <!-- Bla bla meta utf8 on s'en fout… -->
    <title>~La fumée des miettes~</title>

    <style type="text/css">
        /* Vous pouvez écrire du CSS ici */
    </style>

    <script src="TemplateData/UnityProgress.js"></script>
    <!-- Bla bla script machin on s'en fout… -->
</head>

Gérer le positionnement

Notre problème principal est que le bouton est mal positionné. Mettons que je veuille le mettre dans le coin en bas à gauche de mon écran de jeu. Je vais d'abord dire, dans mon CSS, un truc du genre "Eh, est-ce que tu veux bien me prendre mon fsButton et régler sa position, stp ?"

<style type="text/css">
    .fsButton {
        position: absolute;
    }
</style>

Note : En CSS, on attribue un style à une balise (par exmple <img> ou <button>) en mentionnant simplement son nom : img { position: absolute; }. Toutefois, j'ai mis un point devant le nom de mon élément, dans l'exemple au dessus, pour préciser qu'il s'agit de sa classe et pas de son nom de balise. Ainsi, .fsButton { position: absolute; } va s'appliquer aux éléments qui ont pour attribut class="fsButton".
Exemple : img { position: absolute; } s'applique à TOUTES les balises <img> du html.
.image-du-header { position: absolute; } s'applique aux balises qui ont l'attribut class="image-du-header".

/!\ N'oubliez pas les point-virgules en CSS !

La ligne position: absolute; permet de positionner l'élément librement. Maintenant, je vais rajouter une autre ligne.

<style type="text/css">
    .fsButton {
        position: absolute;
        bottom: 0px;
    }
</style>

bottom: 0px; veut littéralement dire : "colle ton cul à 0 pixels". L'élément va donc positionner son côté bas à 0px du bas de l'élément parent, qui fait la taille de l'écran de jeu. Bref, le bouton se colle en bas de l'écran. Voici ce que ça donne :

C'est pas très élégant. On va rajouter une marge autour de notre bouton pour qu'il ne soit pas collé au bord. Et, ça tombe bien, y'a un truc qui s'appelle margin :

<style type="text/css">
    .fsButton {
        position: absolute;
        bottom: 0px;
        margin: 16px;
    }
</style>

margin: 16px; va créer une marge invisible de 16px tout autour de l'élément en question. Ce qui nous donne ceci :

C'est de mieux en mieux ! Si vous vouliez positionner votre bouton en bas à droite, il vous suffirait d'écrire ceci :

<style type="text/css">
    .fsButton {
        position: absolute;
        bottom: 0px;
        margin: 16px;
        right: 0px; /*pareil que bottom, mais c'est pour la droite */
    }
</style>

Faire les choses comme des pros

Je ne compte pas m'arrêter là. Vous l'avez sans doute remarqué, mais généralement, lorsque vous survolez un élément intéractif avec la souris (bouton, lien, etc.), cet élément réagit, change de couleur, devient plus opaque… Ce sont des choses qui sont aussi gérées par le CSS ! Voici un exemple (et je me suis appliquée, hein !), survolez le bouton ci-dessous avec votre souris.

Je suis un bouton

Vous voyez que le bouton ce-dessus devient plus foncé lors du survol avec le curseur. En voici une autre version :

Je suis un bouton plus doux

Ce dernier bouton a un quelque chose en plus : une transition. Cette transition est ce qui rend l'apparition plus douce, moins abrupte et si satisfaisante. Je suis sûre que vous avez essayé de cliquer ! Sans plus attendre, je vous montre le CSS derrière tout ça :

<style type="text/css">
    .monBouton { 
        /* (Je montre pas tout parce qu'on s'en fout) */

        /* L'opacité est réglée à 40%*/
        opacity: 0.4;
    }

    .monBouton:hover {
        /* Ce CSS n'est actif qu'au survol du curseur*/
        /* Opacité maximale : 100% */
        opacity: 1;
        /* Je change l'apparence du curseur pour signaler que le bouton est cliquable */
        cursor: pointer;
    }
</style>

Note : En CSS, il existe ce qu'on appelle des sélecteurs. Sans rentrer dans les détails, :hover est un sélecteur qui permet de n'appliquer le CSS que lorsque la souris survole l'élément. Le réglage de l'opacité à 100% va alors remplacer le précédent (40%), et ce jusqu'à ce que le curseur ne survole plus l'élément.

Pour obtenir ma transition si douce et satisfaisante, je rajoute une ligne qui s'appelle… transition. Quelle surprise.

<style type="text/css">
    .monBouton { 
        /* L'opacité est réglée à 40%*/
        opacity: 0.4;
        /* L'effet de transition est appliqué à l'opacité, et dure 0.4 secondes */
        transition: opacity 0.4s;
    }

    .monBouton:hover {
        /* Ce CSS n'est actif qu'au survol du curseur*/
        /* Opacité maximale : 100% */
        opacity: 1;
        /* Je change l'apparence du curseur pour signaler que le bouton est cliquable */
        cursor: pointer;
    }
</style>

Si on applique ces lignes de CSS à notre bouton de jeu, alors voilà ce que ça donne :

<style type="text/css">
    .fsButton {
        position: absolute;
        bottom: 0px;
        right: 0px;
        margin: 16px;
        opacity: 0.4;
        transition: opacity 0.4s;
    }

    .fsButton:hover {
        opacity: 1;
        cursor: pointer;
    }
</style>

Dernière étape : envoyer la sauce

En guise de récapitulatif, voici ce à quoi devrait ressembler votre index.html. Lisez attentivement et veillez à ce que vous ayez la même chose (ou copiez-collez attentivement, on va pas se mentir, c'est plus confort).

<!DOCTYPE html>
<html lang="en-us">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>~La fumée des miettes~</title>
    <link rel="shortcut icon" href="VelData/favicon.ico">
    <link rel="stylesheet" href="TemplateData/style.css">
    <style type="text/css">
        .fsButton {
            position: absolute;
            bottom: 0px;
            right: 0px;
            margin: 16px;
            opacity: 0.4;
            transition: opacity 0.4s;
        }

        .fsButton:hover {
            opacity: 1;
            cursor: pointer;
        }
    </style>
    <script src="TemplateData/UnityProgress.js"></script>
    <script src="Build/UnityLoader.js"></script>
    <script>
      var unityInstance = UnityLoader.instantiate("unityContainer", "Build/fumee-des-miettes V6.json", {onProgress: UnityProgress});
    </script>
  </head>
  <body>
    <div class="webgl-content">
      <div id="unityContainer" style="width: 960px; height: 600px"></div>
      <div class="fsButton" title="Fullscreen" onclick="unityInstance.SetFullscreen(1)">
        <img src="VelData/enlarge.svg" width="60" height="60"> </img>
      </div>
      <!-- <div class="footer">
        <div class="webgl-logo"></div>
        <div class="fullscreen" onclick="unityInstance.SetFullscreen(1)"></div>
        <div class="title">TOASTEUR</div>
      </div> -->
    </div>
  </body>
</html>

Une fois que tout ça a bien été sauvegardé, il ne reste plus qu'à poster ça sur itch.io! À moins d'avoir un serveur local, vous ne pourrez pas voir le résultat vous-même. Le tout doit être lancé depuis un serveur, comme celui d'itch.io par exemple. Compressez le dossier contenant index.html, TemplateData et Build en un .zip, et téléversez ce dossier compressé sur la page de votre jeu. Je tiens à donner une dernière précision sur ce qu'il y a à cocher pour votre publication :

Et voila ! Si vous avez suivi correctement ce tutoriel, ça devrait marcher… Mais je vais pas vous mentir. Franchement, ça ne marche jamais du premier coup. Mais c'est aussi ça, la prog ; se tromper, réessayer, comprendre ses boulettes, et pédaler dans des tutoriels et de la documentation jusqu'à y arriver ! Et si vous y êtes arrivé⋅e⋅s du premier coup, alors là bravo.

— Velvet

Velvet