Cherchez Unity

Utilisation de prefabs light baked sur des appareils mobiles

et autres astuces bon marché simples par seconde sur les téléphones bas de gamme

Last updated: January 2019

What you will get from this page: Michelle Martin, software engineer at MetalPop Games explains how they optimized their new mobile strategy game, Galactic Colonies, for a range of mobile devices, so they could reach as many potential players as possible.

MetalPop Games faced the challenge of making a game in which players could build huge cities on their low-end devices, without their framerate dropping or their device overheating. See how they found a balance between good-looking visuals and solid performance.

Construction de ville sur des appareils bas de gamme

As powerful as mobile devices are today, it is still very difficult to run large and good looking game environments at a solid frame rate. Achieving solid 60fps in a large scale 3d environment on an older mobile device can be quite a challenge.

As developers we could just target high-end phones and assume that most players will have good enough hardware to run our game smoothly. But this will result in locking out a huge amount of potential players, as there are still many older devices in use. Those are all potential customers you don’t want to exclude if it can be avoided.

In our game Galactic Colonies, the players colonize alien planets and can build huge colonies made up from a large number of individual buildings. While smaller colonies might only have a dozen buildings, larger ones can easily have hundreds of them.

This is what our goal list looked like when we started building our pipeline:

  • We want huge maps with a high amount of buildings
  • We want to fast run on cheaper and/or older mobile devices
  • We want nice looking lights and shadows
  • We want an easy and maintainable production pipeline
L'éclairage dans les jeux mobiles : les défis habituels

Avoir un bon éclairage dans votre jeu est la clé pour un rendu sublime de vos modèles 3D. Dans Unity, c'est bien sûr très simple : réglez votre niveau, placez vos lumières dynamiques et vous êtes prêt. Et si vous avez besoin de garder un œil sur la performance, il vous suffit de travailler toutes vos lumières et d'ajouter un peu de SSAO et d'autres petites fantaisies pour le plaisir des yeux via la pile de post-traitement. Et voilà !

La mise en place de l'éclairage dans les jeux mobiles nécessite souvent une bonne quantité d'astuces et de solutions de contournement. Par exemple, à moins que vous ne visiez des appareils haut de gamme, il vaut mieux ne pas utiliser d'effets de post-traitement du tout. De même, avoir une grande scène pleine de lumières dynamiques diminuera votre fréquence d'image de façon drastique.

L'éclairage en temps réel peut être très coûteux, même sur un PC de bureau. Sur les appareils mobiles, les limites des ressources sont encore plus strictes et vous ne pouvez pas vous permettre toutes ces fonctionnalités que vous aimeriez utiliser.

Le travail de l'éclairage à la rescousse

Sur les appareils mobiles, les ressources sont assez limitées et vous ne voulez pas épuiser les batteries de vos utilisateurs plus que nécessaire en ayant trop de lumières fantaisistes dans votre scène.

Si vous poussez constamment un appareil jusqu'à ses limites matérielles, le téléphone surchauffera et, par conséquent, s'éteindra automatiquement pour se protéger. C'est là que vous commenceriez habituellement à adapter chaque lumière qui n'a pas besoin de projeter des ombres en temps réel.

Unity light baked prefabs for mobile MetalPopGames Galactic Colonies

(Un niveau typique dans les colonies galactiques avec un grand nombre de bâtiments)

Pour nous, ce n'était pas une option, car notre monde de jeu est construit en temps réel par le joueur. La découverte constante de nouvelles régions, la construction de nouveaux bâtiments ou l'amélioration des bâtiments existants empêchent toute forme d'adaptation efficace de l'éclairage.

Fais semblant, et le reste suivra

Le processus de travail de la lumière consiste à pré-calculer les hautes lumières et les ombres d'une scène (statique) et à stocker l'information sur une lightmap.

Le processus consiste à dire au moteur de rendu où rendre un modèle plus clair ou plus foncé, créant ainsi l'illusion de la lumière.

Le rendu de cette façon est vraiment rapide, parce que tous les calculs de lumière lents et coûteux ont été faits hors ligne, et au moment de l'exécution, le moteur de rendu (shader) a juste besoin de regarder le résultat dans une texture.

Il y a pourtant un compromis : vous devrez envoyer des textures de lightmap supplémentaires qui augmenteront la taille de votre compilation et nécessiteront de la mémoire de texture supplémentaire au moment de l'exécution.

Vous perdrez aussi de l'espace parce que vos mailles auront besoin d'UV de lightmap et grandiront un peu.

Dans l'ensemble, vous obtiendrez un gain de vitesse énorme.

Unity light baked prefabs for mobile MetalPopGames

(Un bâtiment avec et sans lightmap)

Cependant, appuyer simplement sur le bouton Bake ne fonctionnera pas si vous avez un monde dynamique qui peut être constamment modifié par le joueur.

Nous sommes confrontés à un certain nombre de problèmes qui surviennent lors du travail de la lumière pour des scènes très modulaires.

Travailler l'éclairage avec des prefabs n'est pas si simple

Tout d'abord, les données d'éclairage dans Unity sont stockées et directement associées aux données de scène. Ce n'est pas un problème si vous avez des niveaux individuels et des scènes pré-compilées et que vous n'avez qu'une poignée d'objets dynamiques. Vous pouvez prétravailler l'éclairage, tout simplement.

Cela ne fonctionne évidemment pas lorsque vous créez des niveaux de façon dynamique. Dans un jeu de construction de ville, le monde n'est pas pré-créé. Au lieu de cela, il est largement assemblé dynamiquement et à la volée selon la décision du joueur concernant ce qu'il doit construire et où il doit le construire. Cela se fait généralement en instanciant les prefabs là où le joueur décide de construire quelque chose.

La seule solution à ce problème est de stocker toutes les données d'éclairage pertinentes à l'intérieur du prefab et non de la scène.

Malheureusement, il n'existe pas de solution simple pour copier les données de la lightmap à utiliser, ses coordonnées et son échelle dans un prefab.

Construction d'un pipeline pour les prefabs et l'éclairage

La meilleure approche pour obtenir un pipeline solide en manipulant des prefabs avec éclairage travaillé est de créer les prefabs dans une scène différente et séparée (plusieurs scènes, en fait) et de les charger ensuite dans le jeu principal si nécessaire.

Chaque pièce modulaire est légèrement travaillée et sera ensuite chargée dans le jeu si nécessaire.

Quand vous regardez de plus près comment fonctionne le light baking dans Unity, vous pouvez voir que le rendu d'un mesh ne fait qu'appliquer une autre texture et éclaircir, assombrir (ou parfois coloriser) légèrement le mesh. Tout ce dont vous avez besoin, c'est la texture de la lightmap et les coordonnées UV, toutes deux créées par Unity pendant le processus de travail de la lumière.

Pendant le processus de light baking, Unity crée un nouvel ensemble de coordonnées UV (qui pointent vers la texture de la lightmap), un décalage et une échelle pour le maillage individuel. Ces coordonnées changent à chaque fois que la lumière évolue..

Comment utiliser les canaux UV

Pour trouver une solution à ce problème, il est utile de comprendre comment fonctionnent les canaux UV et comment les utiliser au mieux.

Chaque maillage peut avoir plusieurs ensembles de coordonnées UV (appelés canaux UV dans Unity). Dans la majorité des cas, un seul jeu d'UV suffit, car les différentes textures (Diffuse, Spec, Bump, etc) stockent toutes les informations au même endroit dans l'image.

Mais lorsque des objets partagent une texture, comme une lightmap, et ont besoin de rechercher les informations d'un endroit très spécifique dans une grande texture, il est souvent impossible d'ajouter un autre ensemble d'UV pour utiliser cette texture partagée.

L'inconvénient d'utiliser plusieurs coordonnées UV est que celles-ci consomment plus de mémoire. Si vous utilisez deux jeux d'UV au lieu d'un seul, CHAQUE vertex du maillage a deux fois plus de coordonnées UV. Pour chaque vertex, vous stockez deux nombres à virgule flottante supplémentaires, et vous les téléchargez également sur le GPU lors du rendu.

Création des prefabs

Unity est utilisé pour générer les coordonnées et la lightmap, en utilisant la fonctionnalité de light baking. Le moteur écrira les coordonnées UV de la lightmap dans le deuxième canal UV du modèle. Il est important de noter que l'ensemble primaire de coordonnées UV ne peut pas être utilisé pour cela, car le modèle doit être déballé.

Imaginez une boîte utilisant la même texture pour chacun de ses côtés : les différents côtés de la boîte ont tous les mêmes coordonnées UV, car ils réutilisent la même texture. Mais cela ne fonctionnera pas pour un objet photographié, car chaque côté de la boîte est frappé individuellement par les ombres et les lumières. Chaque côté a besoin de son propre espace dans la lightmap avec ses données d'éclairage individuelles. D'où la nécessité d'un nouvel ensemble d'UV.

Donc, pour mettre en place un nouveau light baked prefab tout ce que nous avons à faire est de stocker la texture et ses coordonnées pour qu'elles ne soient pas perdues et de les copier dans le prefab.

Après le travail de la lumière, nous exécutons un script qui parcourt tous les maillages de la scène et écrit les coordonnées UV dans le canal UV2 réel du maillage, avec les valeurs de décalage et d'échelle appliquées.

Le code pour modifier les maillages est relativement simple :

Mesh meshToModify = GetComponent().sharedMesh;
Vector4 lightmapOffsetAndScale = GetComponent().lightmapScaleOffset;

Vector2[] modifiedUV2s = meshToModify.uv2;
for (int i = 0; i < meshToModify.uv2.Length; i++)
{
    modifiedUV2s[i] = new Vector2(meshToModify.uv2[i].x * lightmapOffsetAndScale.x +
    lightmapOffsetAndScale.z, meshToModify.uv2[i].y * lightmapOffsetAndScale.y +
    lightmapOffsetAndScale.w);
}
meshToModify.uv2 = modifiedUV2s;

Pour être un peu plus précis : ceci est fait sur une copie des mailles, et non sur l'original, parce que nous procédons à d'autres optimisations de nos mailles pendant le processus de baking.

Les copies sont automatiquement générées, sauvegardées dans un prefab et assignées à un nouveau matériau avec un shader personnalisé et la lightmap nouvellement créée. Nos mailles d'origine restent ainsi intactes et les prefabs sont immédiatement prêts à l'emploi.

Un shader lightmap personnalisé

Cela rend le flux de travail très simple. Pour mettre à jour le style et l'aspect des graphiques, il suffit d'ouvrir la scène appropriée, d'effectuer toutes les modifications jusqu'à ce que vous soyez satisfait, puis de lancer le processus automatisé de baking et de copie. Lorsque ce processus est terminé, le jeu commencera à utiliser les prefabs et les mailles mis à jour avec l'éclairage actualisé.

La texture réelle de la lightmap est ajoutée par un shader personnalisé, qui applique la lightmap comme seconde texture d'éclairage au modèle pendant le rendu.

Le shader est très simple et court, et en plus d'appliquer la couleur et la lightmap, il calcule un faux effet spéculaire/brillant.

Shader "Custom/LightmappedPrefabWithSpec"
{
  Properties
  {
    _MainTex("Base (RGB)", 2D) = "white" {}
    _Lightmap("Lightmap", 2D) = "white" {}
    _Specmap("Specmap", 2D) = "white" {}
    _SpecularAtt("Glossiness", Range(0.1, 2)) = 0.5
    _SpecularAmt("Specular", Range(0, 1)) = 0.5
  }

  SubShader
  {
    Tags{ "Queue" = "Geometry+1" }
    Pass
    {
      CGPROGRAM

      // Defining the name of the vertex shader
      #pragma vertex vert

      // Defining the name of the fragment shader
      #pragma fragment frag


      // Include some common helper functions,
      // specifically UnityObjectToClipPos and DecodeLightmap.
      #include "UnityCG.cginc"

      // Color Diffuse Map
      sampler2D _MainTex;
      // Tiling/Offset for _MainTex, used by TRANSFORM_TEX in vertex shader
      float4 _MainTex_ST;


      // Lightmap (created via Unity Lightbaking)
      sampler2D _Lightmap;
      // Tiling/Offset for _Lightmap, used by TRANSFORM_TEX in vertex shader
      float4 _Lightmap_ST;

      // Grayscale Map indicating which parts of the models have specular
      // Note: _Specmap_ST is not needed, as this map is using the same
      // UVs as for the _MainTex.
      sampler2D _Specmap;

      // This is the vertex shader input: position, UV0, UV1, normal
      // UV1 (= second UV channel) needed for the lightmap texture coordinates
      struct appdata
      {
        float4 vertex   : POSITION;
        float2 texcoord : TEXCOORD0;
        float2 texcoord1: TEXCOORD1;
        float3 normal: NORMAL;
      };

      // This is the data passed from the vertex to fragment shader
      struct v2f
      {
        float4 pos  : SV_POSITION; // position of the pixel
        float2 txuv : TEXCOORD0; // for accessing the diffuse color map
        float2 lmuv : TEXCOORD1; // for accessing the light map
        float3 normalDir : TEXCOORD2; // for fake specular
      };

      // This is the vertext shader, doing nothing special at all.
      // Most notably it is calculating the surface normal, because that
      // is needed for the fake specular lighting in the fragment shader.
      v2f vert(appdata v)
      {
        v2f o;
        o.pos = UnityObjectToClipPos(v.vertex);
        o.txuv = TRANSFORM_TEX(v.texcoord.xy, _MainTex); // using _MainTex_ST
        o.lmuv = TRANSFORM_TEX(v.texcoord1.xy, _Lightmap); // using _Lightmap_ST

        // Calculating the normal of the vertex for the fragment shader
        float4x4 modelMatrixInverse = unity_WorldToObject;
        o.normalDir = normalize(mul(float4(v.normal, 0.0), modelMatrixInverse).xyz);

        return o;
      }

      uniform float _SpecularAtt;
      uniform float _SpecularAmt;

      // Fragment Shader
      half4 frag(v2f i) : COLOR
      {
        // Reading color directly from the diffuse texture, using first UV channel
        half4 col = tex2D(_MainTex, i.txuv.xy);
        // Reading specular (on/off) value from spec map texture
        half4 specVal = tex2D(_Specmap, i.txuv.xy);
        // Reading lightmap value from the lightmap texture
        half4 lm = tex2D(_Lightmap, i.lmuv.xy);

        // Fake specular light angle calculation with a hard-coded light direction
        half3 th = normalize(half3(0, 1, -0.25));
        float spec = max(0, dot(i.normalDir, th));

        // Adjusting by overall specular amount and glossyness (material parameters)
        spec = _SpecularAmt * pow(spec, 40.0 * _SpecularAtt);
        // We're just using red value of the specular texture, like a grayscale map,
        // although technically spec could be colored.
        // Example: float3 specCol = specVal * spec;
        spec = spec * specVal.r;

        // Calculating the final color of the pixel by bringing it all together
        col.rgb = min(half4(1,1,1,1), col.rgb * DecodeLightmap(lm) + col.rgb * spec);
        return col;
      }
      ENDCG
    }
  }
  Fallback "Diffuse"
}

Voici une image d'une configuration matérielle utilisant le shader précédent :

Unity light baked prefabs for mobile Material setup MetalPopGames

(Configuration matérielle à l'aide d'un shader personnalisé)

Installation et traitement de lots en statique

Dans notre cas, nous avons quatre scènes différentes avec tous les prefabs installés. Notre jeu met en vedette différents biomes comme les tropiques, l'arctique, le désert, etc. et nous divisons nos scènes en conséquence. Pour votre jeu, le nombre de scènes peut varier en fonction de vos besoins.

Tous les prefabs qui seront utilisés dans une scène donnée partagent une seule lightmap. Cela signifie une seule texture supplémentaire, en plus du fait que les prefabs ne partagent qu'un seul matériau.

En conséquence, nous avons été en mesure de rendre tous les modèles statiques et de rendre par lots presque tout notre monde en une seule requête.

Unity light baked prefabs for mobile bake level MetalPopGames

(Le niveau de baking dans l'éditeur Unity)

Les scènes avec light baking, dans lesquelles tous nos carrelages/bâtiments sont installés, ont des sources de lumière supplémentaires pour créer des points culminants localisés. Vous pouvez placer autant de lumières que vous le souhaitez dans les scènes de montage, car elles seront toutes travaillées.

Le processus de baking est géré dans un dialogue d'interface utilisateur personnalisé qui prend en charge toutes les étapes nécessaires. Il s'assure que :

  • The correct material is assigned to all meshes
  • Hides everything that doesn’t need to be baked during the process
  • Combines/bakes the meshes
  • Copies the UVs and creates prefabs
  • Names everything correctly and checks out the necessary files from the version control system

Unity light baked prefabs for mobile custom inspector MetalPopGames

(Inspecteur personnalisé pour un flux de production simple)

Des prefabs correctement nommés sont créés à partir des mailles pour que le code du jeu puisse les charger et les utiliser directement. Les méta-fichiers sont également modifiés au cours de ce processus, de sorte que les références aux maillages des prefabs ne soient pas perdues.

Ce flux de travail nous permet de peaufiner nos bâtiments autant que nous le voulons, de les éclairer comme nous l'entendons et de laisser le script s'occuper de tout.

Lorsque nous revenons à notre scène principale et que nous exécutons le jeu, cela fonctionne - aucune intervention manuelle ou autre mise à jour n'est nécessaire.

Lumière artificielle et bits dynamiques

L'un des inconvénients évidents d'une scène dans laquelle 100 % de l'éclairage est prétravaillé, c'est qu'il est difficile d'avoir des objets dynamiques ou des mouvements. Tout ce qui projette une ombre nécessiterait un calcul en temps réel de la lumière et de l'ombre, ce que, bien entendu, nous voudrions éviter. Mais sans aucun objet en mouvement, l'environnement 3D apparaîtrait statique et mort.

Nous étions prêts à faire avec certaines restrictions bien sûr, car notre priorité était d'obtenir de bons visuels et un rendu rapide. Pour créer l'impression d'une colonie spatiale ou d'une ville vivante et en mouvement, peu d'objets doivent obligatoirement se déplacer. Et la plupart d'entre eux ne nécessitent pas nécessairement des ombres. Du moins, l'absence de l'ombre ne serait pas remarquée.

Dans notre cas, nous avons commencé par diviser tous les blocs de construction de la ville en deux prefabs distincts. Une partie statique, qui contenait la majorité des vertex, tous les bits complexes de nos maillages - et une partie dynamique, contenant le moins de vertex possible.

Les parties dynamiques d'un prefab sont des bits animés placés sur les parties statiques. La lumière n'est pas travaillée, et nous avons utilisé un faux shader d'éclairage très rapide et bon marché pour créer l'illusion que l'objet était éclairé de façon dynamique.

Shader "Custom/FakeLighting"
{
  Properties
  {
    _Color ("Color", Color) = (1,1,1,1)
    _Brightness ("Brightness", Range(0,1)) = 0.4
    _MainTex ("Albedo (RGB)", 2D) = "white" {}
  }

  SubShader
  {
    Tags { "RenderType" = "Opaque" }
    LOD 200
    Pass
    {

      CGPROGRAM

      // Define name of vertex shader
      #pragma vertex vert
      // Define name of fragment shader
      #pragma fragment frag

      // Include some common helper functions, such as UnityObjectToClipPos
      #include "UnityCG.cginc"

      float4 _Color;
      float _Brightness;

      // Color Diffuse Map
      sampler2D _MainTex;
      // Tiling/Offset for _MainTex, used by TRANSFORM_TEX in vertex shader
      float4 _MainTex_ST;

      // This is the vertex shader input: position, UV0, UV1, normal
      struct appdata
      {
        float4 vertex   : POSITION;
        float2 texcoord : TEXCOORD0;
        float3 normal: NORMAL;
      };

      // This is the data passed from the vertex to fragment shader
      struct v2f
      {
        float4 pos  : SV_POSITION;
        float2 txuv : TEXCOORD0;
        float3 normalDir : TEXCOORD2;
      };

      // This is the vertex shader
      v2f vert(appdata v)
      {
        v2f o;
        o.pos = UnityObjectToClipPos(v.vertex);
        o.txuv = TRANSFORM_TEX(v.texcoord.xy,_MainTex);

        // Calculating normal so it can be used for fake lighting
        // in the fragment shader
        float4x4 modelMatrixInverse = unity_WorldToObject;
        o.normalDir = normalize(mul(float4(v.normal, 0.0), modelMatrixInverse).xyz);

        return o;
      }

      // This is the fragment shader
      half4 frag(v2f i) : COLOR
      {
        // Reading color from diffuse texture
        half4 col = tex2D(_MainTex, i.txuv.xy);

        // Using hard-coded light direction for fake lighting
        half3 th = normalize(half3(0.25, 1, -0.25));
        // Using hard-coded light direction for fake specular
        // This matches the value inside the LightmappedPrefabWithSpec shader
        half3 sth = normalize(half3(0, 1, -0.25));

        // Fake lighting
        float lightVal = max(0, dot (i.normalDir, th));
        float lightScale = 0.75;
        lightVal = lightVal * lightScale;

        // Fake spec
        float spec = max(0, dot(i.normalDir, sth));
        float specScale = 0.65;
        float specAtt = 0.65;
        spec = specScale * pow (spec, 40.0 * specAtt);

        // Add in a general brightness (similar to ambient/gamma) and then
        // calculate the final color of the pixel
        col.rgb = min(half4(1,1,1,1), col.rgb * _Brightness +
                      col.rgb * lightVal * _Color + col.rgb * spec);
        return col;
      }

      ENDCG
    }
  }
  FallBack "Diffuse"
}

Les objets n'ont pas d'ombre, ou nous avons créé une fausse ombre dans le bit dynamique. La plupart de nos surfaces sont planes, donc dans notre cas ce n'était pas un gros obstacle.

Unity light baked prefabs for mobile Galactic Colonies MetalPopGames

(Bâtiments utilisant des objets dynamiques supplémentaires)

Il n'y a pas d'ombres sur les bits dynamiques mais c'est à peine perceptible, à moins que vous ne sachiez que chercher. L'éclairage des prefabs dynamiques est également complètement faux - il n'y a pas du tout d'éclairage en temps réel.

Le premier raccourci que nous avons pris a été de coder en dur la position de notre source lumineuse (soleil) dans le faux shader d'éclairage. C'est une variable de moins dont le shader a besoin pour rechercher et se remplir dynamiquement à partir du monde.

Il est toujours plus rapide de travailler avec une constante qu'avec une valeur dynamique. Cela nous a permis d'obtenir un éclairage de base et des côtés clairs et sombres des mailles.

Spéculaire/brillant

Pour rendre les choses un peu plus brillantes, nous avons ajouté un faux calcul spéculaire/brillant aux shaders pour les objets dynamiques et statiques. Les reflets spéculaires aident à créer un aspect métallique, mais aussi à transmettre la courbure d'une surface.

Les reflets spéculaires étant une forme de réflexion, l'angle de la caméra et la source lumineuse l'un par rapport à l'autre sont nécessaires pour les calculer correctement. Lorsque la caméra bouge ou tourne, le spéculaire change. Tout calcul de shader nécessiterait l'accès à la position de la caméra et à toutes les sources de lumière de la scène.

Cependant, dans notre jeu, nous n'avons qu'une seule source de lumière que nous voulons utiliser pour le spéculaire : le soleil. Dans notre cas, le soleil ne bouge jamais et peut être considéré comme une lumière directionnelle. Nous pouvons simplifier le shader en n'utilisant qu'une seule lumière, et en prenant simplement une position fixe et un angle d'entrée pour celle-ci.

Mieux encore, notre caméra dans Galactic Colonies montre la scène de haut en bas, comme dans la plupart des jeux de construction de villes. La caméra peut être légèrement inclinée et zoomée en avant et en arrière, mais elle ne peut pas tourner autour de l'axe vers le haut.

Dans l'ensemble, elle regarde toujours l'environnement d'en haut. Pour simuler un look spéculaire, nous avons prétendu que la caméra était complètement fixe, et que l'angle entre la caméra et la lumière était toujours le même.

De cette façon, nous pouvions à nouveau coder en dur une valeur constante dans le shader et obtenir un effet spec/gloss.

Unity light baked prefabs for mobile Galactic Colonies MetalPopGames

(Faux effet spéculaire/brillant)

L'utilisation d'un angle fixe pour le spéculaire est bien sûr techniquement incorrecte, mais il est pratiquement impossible de faire la différence tant que l'angle de la caméra ne change pas beaucoup. Pour le joueur, la scène aura toujours l'air correcte, ce qui est le point essentiel de l'éclairage en temps réel.

Éclairer un environnement dans un jeu vidéo en temps réel est et a toujours été une question d'apparence visuelle apparaissant correcte, plutôt qu'une simulation physique être correcte.

Parce que presque tous nos maillages partagent un seul matériau, avec beaucoup de détails provenant de la carte optique et des vertex, nous avons ajouté une carte de texture spéculaire, pour indiquer au shader quand et où appliquer la valeur spéculative, et avec quelle force. L'accès à la texture se fait par le canal UV primaire, ce qui évite d'avoir besoin d'un jeu de coordonnées supplémentaires. Et parce qu'il n'y a pas beaucoup de détails, sa résolution est très basse, n'occupant que très peu d'espace.

Pour certains de nos plus petits bits dynamiques avec un faible nombre de vertex, nous pourrions même utiliser le dosage dynamique automatique de Unity, ce qui accélérerait encore le rendu.

Des prefabs light baked par dessus des prefabs light baked

Toutes les ombres travaillées peuvent parfois créer de nouveaux problèmes, surtout lorsque l'on travaille avec des bâtiments relativement modulaires. Dans un projet, nous avions un entrepôt que le joueur pouvait construire pour afficher le type de marchandises qui y étaient entreposées sur le bâtiment réel.

Cela cause des problèmes puisque nous avons deux objets travaillées l'un sur l'autre. Lightbake-ception !

Nous avons abordé le problème en utilisant encore une autre astuce simple :

  • The surface where the additional object was to be added had to be flat and use a specific gray color matching the base building
  • In return for that trade-off, we could bake the objects on a smaller flat surface and place it on top of the area with just a slight offset
  • Lights, highlights, colored glow and shadows were all baked into the tile

Unity light baked prefabs for mobile Galactic Colonies MetalPopGames

(Les objets travaillés utilisent une lueur bleue et projettent une ombre)

Un travail de l'éclairage efficace - si vous pouvez faire avec des restrictions.

Construire et travailler nos prefabs de cette façon nous permet d'avoir d'énormes cartes avec des centaines de bâtiments tout en gardant un très faible nombre d'appels. Tout notre monde de jeu est plus ou moins rendu avec un seul matériau et nous sommes à un point où l'interface utilisateur utilise plus d'appels que notre monde de jeu. Moins il y a de matériaux différents à rendre, plus la performance de votre jeu est élevée.

Cela nous permet d'ajouter plus de choses à notre monde, comme des particules, des effets météorologiques et d'autres éléments pour le plaisir des yeux.

De cette façon, même les joueurs avec des appareils plus anciens peuvent construire de grandes villes avec des centaines de bâtiments tout en gardant une stabilité à 60 fps.

Unity light baked prefabs for mobile Galactic Colonies MetalPopGames

(Une colonie construite par un joueur utilisant des prefabs light baked)

Choisissez ce qui convient à votre jeu

Notre solution pour le rendu de grandes planètes avec des villes très fréquentées est adaptée à notre jeu. Nous avons choisi ce qui fonctionne pour nous. Nous avons utilisé nos angles de prise de vue limités et la source de lumière unique de la scène pour réduire considérablement la complexité des shaders. Cela nous a également permis de réaliser des économies en termes d'éclairage d'objets dynamiques et de calcul spéculaire avec un angle fixe. Nous avons réduit le nombre d'objets dynamiques et mis le reste en lots statiquement.

Et bien sûr, notre style visuel low poly couleur suniquement facilite aussi beaucoup de choses, car il nous permet de partager les matériaux entre presque tous les objets, ce qui rend possible à la fois le dosage statique et dynamique.

Très probablement, vous ne serez pas en mesure d'appliquer toutes les solutions décrites ici à votre jeu, et ce n'est pas grave, car ce n’est pas le but. Ce sont des points de départ sur lesquels vous pouvez vous appuyer pour trouver les meilleurs moyens d'optimiser votre propre jeu. Trouvez les restrictions et les limitations avec lesquelles votre jeu peut fonctionner, et utilisez-les pour accélérer votre jeu.

Plus de ressources

Dites-nous si vous avez aimé ce contenu !

Oui, continuez comme ça Ça pourrait être mieux
Compris

Ce site utilise des cookies dans le but de vous offrir la meilleure expérience possible. Consultez la page de politique des cookies pour en savoir plus.