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;
}
}