using System; using System.IO; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using UnityEditor; using UnityEngine; using YooAsset.Editor; // Run through Unity Pipeline after import_asset. Never writes .meta by hand. public static class ImportMainMenuMusic { const string ClipPath = "Assets/Bundles/Sound/BGM/CandyCamp_MainMenu_Loop.ogg"; public static string ConfigureAndVerify() { return ConfigureFor(ClipPath, "MainMenu"); } public static string ConfigureSoftAndVerify() { return ConfigureFor("Assets/Bundles/Sound/BGM/MeadowBreeze_MainMenu_Loop.ogg", "MainMenuSoft"); } static string ConfigureFor(string clipPath, string designFolder) { if (EditorApplication.isPlaying) throw new InvalidOperationException("Import music in Edit Mode."); string repo = Directory.GetParent(Application.dataPath).Parent.FullName; string reportDirectory = Path.Combine(repo, "Doc/Design/Sound", designFolder); var preparation = JObject.Parse(File.ReadAllText(Path.Combine(reportDirectory, "generation.json"))); float expectedLength = preparation["loop"]["seconds"].Value(); var importer = AssetImporter.GetAtPath(clipPath) as AudioImporter; if (importer == null) throw new Exception("AudioImporter missing: " + clipPath); var sample = importer.defaultSampleSettings; sample.loadType = AudioClipLoadType.CompressedInMemory; sample.compressionFormat = AudioCompressionFormat.Vorbis; sample.quality = 0.7f; sample.sampleRateSetting = AudioSampleRateSetting.PreserveSampleRate; sample.preloadAudioData = false; importer.defaultSampleSettings = sample; importer.forceToMono = false; importer.loadInBackground = true; importer.SaveAndReimport(); // Register only the new BGM directory in the existing Art package. var package = BundleCollectorSettingData.Setting.Packages.Find(p => p.PackageName == "Art"); if (package == null) throw new Exception("Existing Art package missing."); var group = package.Groups.Find(g => g.GroupName == "Sound"); if (group == null) group = BundleCollectorSettingData.CreateGroup(package, "Sound"); group.ActiveRuleName = nameof(EnableGroup); group.AssetTags = "art"; BundleCollectorSettingData.ModifyGroup(package, group); const string folder = "Assets/Bundles/Sound/BGM"; var collector = group.Collectors.Find(c => c.CollectPath == folder); if (collector == null) { collector = new BundleCollector { CollectPath = folder, CollectorGUID = AssetDatabase.AssetPathToGUID(folder), CollectorType = ECollectorType.MainAssetCollector, AddressRuleName = nameof(AddressByFileName), PackRuleName = nameof(PackSeparately), FilterRuleName = nameof(CollectAll), AssetTags = "art" }; BundleCollectorSettingData.CreateCollector(group, collector); } package.CheckConfigError(); BundleCollectorSettingData.SaveFile(); var clip = AssetDatabase.LoadAssetAtPath(clipPath); if (clip == null || clip.channels != 2 || clip.frequency != 48000 || Math.Abs(clip.length - expectedLength) > 0.05f) throw new Exception("Imported AudioClip dimensions do not match prepared audio."); importer = (AudioImporter)AssetImporter.GetAtPath(clipPath); if (importer.defaultSampleSettings.loadType != AudioClipLoadType.CompressedInMemory) throw new Exception("Expected compressed-in-memory BGM import."); var report = new { asset = clipPath, guid = AssetDatabase.AssetPathToGUID(clipPath), clip.length, clip.samples, clip.channels, clip.frequency, loadType = importer.defaultSampleSettings.loadType.ToString(), compression = importer.defaultSampleSettings.compressionFormat.ToString(), quality = importer.defaultSampleSettings.quality, importer.loadInBackground, preloadAudioData = importer.defaultSampleSettings.preloadAudioData, package = "Art", group = "Sound", address = Path.GetFileNameWithoutExtension(clipPath), packRule = collector.PackRuleName, runtimePlaybackWired = false, bundleBuilt = false, verifiedUtc = DateTime.UtcNow.ToString("o") }; string json = JsonConvert.SerializeObject(report, Formatting.Indented); File.WriteAllText(Path.Combine(reportDirectory, "unity_validation.json"), json); return json; } }