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é.");
}
}
}