As part of my game, I stream room prefabs at runtime from asset bundles. I’ve found that one of the biggest causes of lag is the initial shader load for any new shaders that the prefabs use. I’ve got a pipeline set up to load shaders from a variant collection, but I was wondering if there was a way to automate the variant collection generation
Currently, I am having to run through the game before building in order to grab all the shader variants that are used in my level to create the collection to preload. However, I would love to be able to automate this as it is tedious to do this each time, as well as makes modding a lot harder. Would it be possible to just grab the materials, particles, etc inside of a room prefab at build time, and figure out what shader variants to generate based on that? I am currently running Unity 2018.2
I threw together a possible way to generate them, however I am stumped by where I get the pass type from as per the constructor: Unity - Scripting API: ShaderVariant
As far as I can tell this would require converting this: Unity - Scripting API: Material.GetPassName
to this: Unity - Scripting API: PassType
private void GenerateCollection() {
GameObject[] precombines = PrecombineAssetMap.GetAllPrecombines();
ShaderVariantCollection newCollection = new ShaderVariantCollection();
for (int i = 0; i < precombines.Length; i++) {
Renderer[] renderers = precombines[i].GetComponentsInChildren<Renderer>();
for (int j = 0; j < renderers.Length; j++) {
Material[] mats = renderers[j].sharedMaterials;
for (int k = 0; k < mats.Length; k++) {
var variants = GetShaderVariants(mats[k]);
for (int x = 0; x < variants.Length; x++) {
if (!newCollection.Contains(variants[x])) {
newCollection.Add(variants[x]);
}
}
}
}
}
}
private ShaderVariantCollection.ShaderVariant[] GetShaderVariants(Material m) {
var collection = new ShaderVariantCollection.ShaderVariant[m.passCount];
for (int i = 0; i < m.passCount; i++) {
// Just using 0 as a placeholder here, need to figure out how to actually get it from the material
collection[i] = new ShaderVariantCollection.ShaderVariant(m.shader, 0, m.shaderKeywords);
}
return collection;
}
Thanks!
EDIT: Looks like I’m not the only one with this question: ShaderVariantCollection best practises?