using System; using System.IO; using System.Linq; using HotUpdate.Gameplay; using Newtonsoft.Json; using UnityEditor; using UnityEditor.SceneManagement; using UnityEngine; using UnityEngine.SceneManagement; /// Pipeline authoring of the UiSfx prefab: one AudioSource plus the v3 synthesized UI clips in UiSound order. public static class BuildUiSfx { public const string PrefabPath = "Assets/Bundles/Sound/Prefab/UiSfx.prefab"; const string ClipFolder = "Assets/Bundles/Sound/SFX/UI/"; public static string Build() { if (EditorApplication.isPlaying) throw new Exception("Build UI SFX in Edit Mode"); var names = Enum.GetNames(typeof(UiSound)); var clips = names.Select(n => { string path = ClipFolder + "Ui_" + n + ".wav"; AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); return AssetDatabase.LoadAssetAtPath(path) ?? throw new Exception("Missing " + path); }).ToArray(); var longest = clips.OrderByDescending(c => c.length).First(); if (longest.length > 1f) throw new Exception(longest.name + " is still " + longest.length + "s; import the one-shots first"); var original = SceneManager.GetActiveScene(); var temporary = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene, NewSceneMode.Additive); try { SceneManager.SetActiveScene(temporary); var root = new GameObject(UiSfx.PrefabName); var source = root.AddComponent(); source.playOnAwake = false; source.loop = false; source.spatialBlend = 0; source.volume = .8f; var player = root.AddComponent(); var serialized = new SerializedObject(player); serialized.FindProperty("_source").objectReferenceValue = source; var list = serialized.FindProperty("_clips"); list.arraySize = clips.Length; for (int i = 0; i < clips.Length; i++) list.GetArrayElementAtIndex(i).objectReferenceValue = clips[i]; serialized.ApplyModifiedPropertiesWithoutUndo(); PrefabUtility.SaveAsPrefabAsset(root, PrefabPath); } finally { SceneManager.SetActiveScene(original); EditorSceneManager.CloseScene(temporary, true); } return Verify(); } public static string Verify() { var prefab = AssetDatabase.LoadAssetAtPath(PrefabPath) ?? throw new Exception("Missing " + PrefabPath); var player = prefab.GetComponent(); var audio = prefab.GetComponent(); if (player == null || player.Source != audio || audio.playOnAwake || audio.loop || audio.spatialBlend != 0) throw new Exception("UiSfx prefab configuration invalid"); var rows = Enum.GetValues(typeof(UiSound)).Cast().Select(s => { var clip = player.Clip(s); if (clip == null || clip.name != "Ui_" + s || clip.length > 1f || clip.frequency != 44100) throw new Exception("Bad clip for " + s + ": " + clip?.name); return new { sound = s.ToString(), clip = AssetDatabase.GetAssetPath(clip), seconds = Math.Round(clip.length, 3), clip.channels, clip.frequency }; }).ToArray(); string report = JsonConvert.SerializeObject(new { batch = "ui_sfx_v3", prefab = PrefabPath, address = UiSfx.PrefabName, package = "Art", group = "Sound", volume = audio.volume, sfxToggle = "PrototypeClientPrefs.Sfx", clips = rows, bundleBuilt = false, verifiedUtc = DateTime.UtcNow.ToString("o") }, Formatting.Indented); string repo = Directory.GetParent(Application.dataPath).Parent.FullName; File.WriteAllText(Path.Combine(repo, "Doc/Design/Sound/UiSfx/playback_assets.json"), report); return report; } }