Last active
April 8, 2026 01:30
-
-
Save nemurigi/dea7c0a1fb94f7b9cf1c36481a459ded to your computer and use it in GitHub Desktop.
UdonSharpBehaviourのインポート時、対応するUdonSharpProgramAssetが存在しない場合に自動生成するAssetPostprocessor
This file contains hidden or 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
| // MIT License | |
| // Copyright (c) 2026 nemurigi | |
| using System; | |
| using System.IO; | |
| using System.Reflection; | |
| using UdonSharp; | |
| using UdonSharp.Compiler; | |
| using UdonSharpEditor; | |
| using UnityEditor; | |
| using UnityEngine; | |
| /// <summary> | |
| /// UdonSharpBehaviour のスクリプトがインポートされた際、 | |
| /// 対応する UdonSharpProgramAsset が存在しない場合に自動生成する。 | |
| /// </summary> | |
| public class UdonSharpProgramAssetAutoGenerator : AssetPostprocessor | |
| { | |
| /// <summary> | |
| /// UdonSharpSettings.autoCompileOnModify を reflection で取得する。 | |
| /// </summary> | |
| private static bool GetAutoCompileOnModify() | |
| { | |
| try | |
| { | |
| Assembly udonSharpEditorAssembly = typeof(UdonSharpEditorUtility).Assembly; | |
| Type settingsType = udonSharpEditorAssembly.GetType("UdonSharpEditor.UdonSharpSettings"); | |
| if (settingsType == null) | |
| return false; | |
| MethodInfo getSettingsMethod = settingsType.GetMethod("GetSettings", BindingFlags.Public | BindingFlags.Static); | |
| if (getSettingsMethod == null) | |
| return false; | |
| object settingsInstance = getSettingsMethod.Invoke(null, null); | |
| if (settingsInstance == null) | |
| return false; | |
| FieldInfo autoCompileField = settingsType.GetField("autoCompileOnModify", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); | |
| if (autoCompileField == null) | |
| return false; | |
| object fieldValue = autoCompileField.GetValue(settingsInstance); | |
| return fieldValue is bool enabled && enabled; | |
| } | |
| catch (Exception ex) | |
| { | |
| Debug.LogError($"UdonSharpProgramAssetAutoGenerator: Failed to read UdonSharpSettings.autoCompileOnModify via reflection.\n{ex}"); | |
| return false; | |
| } | |
| } | |
| private static void OnPostprocessAllAssets( | |
| string[] importedAssets, | |
| string[] deletedAssets, | |
| string[] movedAssets, | |
| string[] movedFromAssetPaths, | |
| bool didDomainReload) | |
| { | |
| if (!didDomainReload) | |
| return; | |
| // 1.対象スクリプトの探索と UdonSharpProgramAsset の生成 | |
| bool createdAnyProgramAsset = false; | |
| foreach (string importedAssetPath in importedAssets) | |
| { | |
| if (string.IsNullOrEmpty(importedAssetPath)) | |
| continue; | |
| MonoScript script = AssetDatabase.LoadAssetAtPath<MonoScript>(importedAssetPath); | |
| if (script == null) | |
| continue; | |
| Type scriptClass = script.GetClass(); | |
| // abstract クラス、または UdonSharpBehaviour を継承していないクラスはスキップ | |
| if (scriptClass == null || scriptClass.IsAbstract || !typeof(UdonSharpBehaviour).IsAssignableFrom(scriptClass)) | |
| continue; | |
| if (UdonSharpEditorUtility.GetUdonSharpProgramAsset(scriptClass) != null) | |
| continue; | |
| string programAssetPath = Path.ChangeExtension(importedAssetPath, ".asset")?.Replace('\\', '/'); | |
| if (string.IsNullOrEmpty(programAssetPath) || !programAssetPath.StartsWith("Assets/", StringComparison.Ordinal)) | |
| continue; | |
| if (AssetDatabase.LoadMainAssetAtPath(programAssetPath) != null) | |
| continue; | |
| UdonSharpProgramAsset programAsset = ScriptableObject.CreateInstance<UdonSharpProgramAsset>(); | |
| programAsset.sourceCsScript = script; | |
| try | |
| { | |
| AssetDatabase.CreateAsset(programAsset, programAssetPath); | |
| AssetDatabase.ImportAsset(programAssetPath, ImportAssetOptions.ForceSynchronousImport); | |
| if (AssetDatabase.LoadAssetAtPath<UdonSharpProgramAsset>(programAssetPath) == null) | |
| { | |
| Debug.LogError($"UdonSharpProgramAssetAutoGenerator: Failed to create program asset at '{programAssetPath}' for '{importedAssetPath}'."); | |
| continue; | |
| } | |
| } | |
| catch (Exception ex) | |
| { | |
| Debug.LogError($"UdonSharpProgramAssetAutoGenerator: Exception while creating program asset at '{programAssetPath}' for '{importedAssetPath}'.\n{ex}"); | |
| continue; | |
| } | |
| createdAnyProgramAsset = true; | |
| } | |
| // 2.生成があった場合のみ反映とコンパイル | |
| if (!createdAnyProgramAsset) | |
| return; | |
| AssetDatabase.Refresh(); | |
| bool compileAfterGeneration = GetAutoCompileOnModify(); | |
| if (!compileAfterGeneration) | |
| return; | |
| try | |
| { | |
| UdonSharpCompilerV1.CompileSync(); | |
| } | |
| catch (Exception ex) | |
| { | |
| Debug.LogError($"UdonSharpProgramAssetAutoGenerator: Compile failed after generating program assets.\n{ex}"); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment