using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; namespace MyInfoMate.Vr.EditorTools { /// /// Déclare dans Always Included Shaders les shaders que ce projet ne /// charge que par code. /// /// Le problème que ça règle. Unity n'embarque dans un build que les /// shaders référencés par un matériau présent dans une scène ou dans /// Resources. Un shader obtenu par Shader.Find au runtime n'est /// référencé nulle part au moment du build : il est retiré. Dans l'éditeur tout /// est disponible, donc tout est correct en Play Mode et magenta sur le /// casque — la combinaison la plus coûteuse à diagnostiquer. /// /// C'est le cas de tous les shaders listés ici : /// /// glTFast résout ses shaders par Shader.Find("Shader Graphs/…") /// (ShaderGraphMaterialGenerator.cs:594) — donc tout GLB chargé au /// runtime, c'est-à-dire tout le contenu de l'app ; /// NavigationBounds et HotspotInstance font le même appel /// pour URP/Unlit ; /// SceneMessage utilise un TextMesh, dont le matériau par /// défaut pointe sur GUI/Text Shader. Sans lui, le message d'erreur /// destiné au visiteur serait lui-même illisible. /// /// /// Fait par script et pas à la main pour la même raison que /// : c'est versionné, rejouable, et ça survit à une /// réimportation du projet. /// public static class IncludeRuntimeShaders { /// /// Les noms sont ceux que le code résout au runtime, relevés dans les /// sources — pas devinés. Un nom faux ici est silencieux : le script dira /// « introuvable » au lieu d'ajouter le shader. /// static readonly string[] RequiredShaders = { // glTFast en URP — le rendu de tout GLB chargé au runtime "Shader Graphs/glTF-pbrMetallicRoughness", "Shader Graphs/glTF-unlit", "Shader Graphs/glTF-pbrSpecularGlossiness", // Repères et garde-fous dessinés par code "Universal Render Pipeline/Unlit", // ⚠️ Surtout pas "Universal Render Pipeline/Lit" : 2 359 296 variantes, // au-delà de ce qu'Unity accepte d'embarquer — le build échoue sur // « has too many Shader variants » après 35 minutes de compilation. // Aucun Shader.Find du projet ne le demande : tout ce qui est dessiné // par code est en Unlit, et les GLB passent par les graphes glTFast. // La 360° (E6) — même piège que les autres : magenta sur le casque, // correct dans l'éditeur "Skybox/Panoramic" // ⚠️ Pas de "GUI/Text Shader" non plus, et pour une raison différente : // il vit dans « Library/unity default resources », marqué // HideFlags.DontSave. Le mettre dans cette liste fait échouer le build // sur « An asset is marked with HideFlags.DontSave but is included in // the build » puis « Failed to write file: …/unity_builtin_extra ». // Le TextMesh de SceneMessage n'en a pas besoin : son matériau vient de // la police référencée par le composant, qui est embarquée normalement. }; [MenuItem("MyInfoMate/Embarquer les shaders du runtime")] public static void Include() { var settings = AssetDatabase .LoadAllAssetsAtPath("ProjectSettings/GraphicsSettings.asset") .FirstOrDefault(); if (settings == null) { Debug.LogError("[Shaders] GraphicsSettings.asset introuvable."); return; } var serialized = new SerializedObject(settings); var list = serialized.FindProperty("m_AlwaysIncludedShaders"); var already = new HashSet(); for (var i = 0; i < list.arraySize; i++) { if (list.GetArrayElementAtIndex(i).objectReferenceValue is Shader shader) already.Add(shader); } var added = 0; var missing = new List(); foreach (var name in RequiredShaders) { var shader = Shader.Find(name); if (shader == null) { // Un shader introuvable dans l'éditeur signale soit un package // absent, soit un renommage en amont. Dans les deux cas, se // taire reviendrait à livrer le magenta. missing.Add(name); continue; } if (!already.Add(shader)) continue; list.InsertArrayElementAtIndex(list.arraySize); list.GetArrayElementAtIndex(list.arraySize - 1).objectReferenceValue = shader; added++; } serialized.ApplyModifiedProperties(); AssetDatabase.SaveAssets(); Debug.Log($"[Shaders] {added} shader(s) ajouté(s), " + $"{already.Count} au total dans Always Included Shaders."); if (missing.Count > 0) Debug.LogError("[Shaders] Introuvables, donc toujours magenta au build : " + string.Join(", ", missing) + ". Vérifier que le package correspondant est bien importé."); } } }