-
-
Save gam0022/0b160e3e5596b5c5370bee25e5841933 to your computer and use it in GitHub Desktop.
Unityプロジェクト内に存在するすべてのマテリアルのシェーダーキーワードをShaderVariantCollectionへ登録するツール (Unity2022 / URP14.0.10)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace MyTool | |
{ | |
using System; | |
using UnityEditor; | |
using UnityEngine; | |
using System.Linq; | |
using UnityEngine.Rendering; | |
public class ShaderKeywordCollector : EditorWindow | |
{ | |
[SerializeField] private ShaderVariantCollection shaderVariantCollection; | |
private Vector2 _scrollPosition; | |
private Material[] _materials = { }; | |
private int _materialCount; | |
[MenuItem("Window/Shader Keyword Collector")] | |
public static void ShowWindow() | |
{ | |
GetWindow<ShaderKeywordCollector>("Shader Keyword Collector"); | |
} | |
void OnGUI() | |
{ | |
GUILayout.Label("Shader Keyword Collector", EditorStyles.boldLabel); | |
// ShaderVariantCollection登録フィールド | |
shaderVariantCollection = EditorGUILayout.ObjectField("Shader Variant Collection", shaderVariantCollection, | |
typeof(ShaderVariantCollection), false) as ShaderVariantCollection; | |
// キーワード取得 | |
EditorGUI.BeginDisabledGroup(shaderVariantCollection == null); | |
if (GUILayout.Button("Collect Keywords")) | |
{ | |
Execute(); | |
} | |
EditorGUI.EndDisabledGroup(); | |
GUILayout.Space(16); | |
GUILayout.Label($"Collected Materials ({_materialCount})", EditorStyles.boldLabel); | |
EditorGUI.indentLevel++; | |
_scrollPosition = EditorGUILayout.BeginScrollView(_scrollPosition); | |
DrawCollectedMaterial(); | |
EditorGUI.indentLevel--; | |
EditorGUILayout.EndScrollView(); | |
} | |
private void DrawCollectedMaterial() | |
{ | |
if (_materials == null) | |
{ | |
return; | |
} | |
foreach (var material in _materials) | |
{ | |
if (material == null) | |
{ | |
continue; | |
} | |
var shader = material.shader; | |
if (shader == null) | |
{ | |
continue; | |
} | |
EditorGUILayout.ObjectField(material, typeof(Material)); | |
} | |
} | |
private void Execute() | |
{ | |
if (shaderVariantCollection == null) | |
{ | |
Debug.LogError("Please assign a Shader Variant Collection."); | |
return; | |
} | |
shaderVariantCollection.Clear(); | |
_materials = AssetDatabase.FindAssets("t:Material", new[] { "Assets/" }). | |
Select(guid => AssetDatabase.GUIDToAssetPath(guid)). | |
Select(AssetDatabase.LoadAssetAtPath<Material>).Where(IsCollectTarget).ToArray(); | |
_materialCount = _materials.Length; | |
foreach (var material in _materials) | |
{ | |
if (material.shader == null) continue; | |
AddMaterialVariant(shaderVariantCollection, material); | |
} | |
EditorUtility.SetDirty(shaderVariantCollection); | |
AssetDatabase.SaveAssets(); | |
Debug.Log("Shader keywords collected and added to the Shader Variant Collection."); | |
} | |
/// <summary> | |
/// 登録対象のマテリアルか判別 | |
/// </summary> | |
private static bool IsCollectTarget(Material material) | |
{ | |
if (material == null) | |
{ | |
return false; | |
} | |
if (material.hideFlags == HideFlags.DontSave) | |
{ | |
return false; | |
} | |
var shader = material.shader; | |
if (shader == null) | |
{ | |
return false; | |
} | |
if (shader.hideFlags == HideFlags.DontSave) | |
{ | |
return false; | |
} | |
if (shader.name.StartsWith("Hidden/")) | |
{ | |
return false; | |
} | |
return true; | |
} | |
/// <summary> | |
/// ShaderVariantCollectionへマテリアルのシェーダーキーワードを登録 | |
/// </summary> | |
private static void AddMaterialVariant(ShaderVariantCollection collection, Material material) | |
{ | |
Shader shader = material.shader; | |
if (material.shader == null) return; | |
int subShaderCount = shader.subshaderCount; | |
int passCount = shader.passCount; | |
for (uint subShaderIndex = 0; subShaderIndex < subShaderCount; subShaderIndex++) | |
{ | |
for (uint passIndex = 0; passIndex < passCount; passIndex++) | |
{ | |
AddPassVariant(collection, shader, passIndex, material.shaderKeywords); | |
} | |
} | |
} | |
/// <summary> | |
/// ShaderVariantCollectionへのVariant登録 | |
/// </summary> | |
private static void AddPassVariant(ShaderVariantCollection collection, Shader shader, uint passIndex, | |
string[] keywords) | |
{ | |
var variant = new ShaderVariantCollection.ShaderVariant | |
{ | |
shader = shader, | |
passType = GetLightModePassType(shader, (int)passIndex), | |
keywords = keywords | |
}; | |
collection.Add(variant); | |
} | |
/// <summary> | |
/// PassTypeの取得 | |
/// </summary> | |
private static PassType GetLightModePassType(Shader shader, int passIndex) | |
{ | |
// ShaderのLightModeパスタグの値を利用して、PassTypeを判別 | |
// PassTypeについては https://docs.unity3d.com/ja/2019.4/ScriptReference/Rendering.PassType.html を参照 | |
ShaderTagId lightModeTag = shader.FindPassTagValue(passIndex, new ShaderTagId("LightMode")); | |
bool success = Enum.TryParse<PassType>(lightModeTag.name, true, out PassType passType); | |
if (success) | |
{ | |
return passType; | |
} | |
switch (lightModeTag.name) | |
{ | |
case "SRPDefaultUnlit": | |
case "": // URPでは、LightModeパスタグが指定されていない場合は SRPDefaultUnlit として扱われる | |
return PassType.ScriptableRenderPipelineDefaultUnlit; | |
default: | |
return PassType.ScriptableRenderPipeline; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment