using System; using AlicizaX.Audio.Runtime; using AlicizaX.Editor; using UnityEditor; using UnityEngine; namespace AlicizaX.Audio.Editor { [CustomEditor(typeof(AudioComponent))] internal sealed class AudioComponentInspector : GameFrameworkInspector { private readonly AudioServiceDebugInfo _serviceInfo = new AudioServiceDebugInfo(); private readonly AudioCategoryDebugInfo _categoryInfo = new AudioCategoryDebugInfo(); private readonly AudioAgentDebugInfo _agentInfo = new AudioAgentDebugInfo(); private readonly AudioClipCacheDebugInfo _clipCacheInfo = new AudioClipCacheDebugInfo(); private SerializedProperty m_InstanceRoot = null; private SerializedProperty m_AudioListener = null; private SerializedProperty m_AudioMixer = null; private SerializedProperty m_AudioGroupConfigs = null; private static readonly GUIContent GroupConfigLabel = new GUIContent("音频分组配置"); private static readonly GUIContent CreateButtonLabel = new GUIContent("创建默认配置资源"); private static readonly GUIContent AudioListenerLabel = new GUIContent("音频监听器"); public override void OnInspectorGUI() { base.OnInspectorGUI(); serializedObject.Update(); AudioComponent t = (AudioComponent)target; EditorGUI.BeginDisabledGroup(EditorApplication.isPlayingOrWillChangePlaymode); { EditorGUILayout.PropertyField(m_InstanceRoot); EditorGUILayout.PropertyField(m_AudioListener, AudioListenerLabel); EditorGUILayout.PropertyField(m_AudioMixer); EditorGUILayout.PropertyField(m_AudioGroupConfigs, GroupConfigLabel); if (m_AudioGroupConfigs.objectReferenceValue == null && GUILayout.Button(CreateButtonLabel)) { CreateDefaultConfigAsset(); } } EditorGUI.EndDisabledGroup(); serializedObject.ApplyModifiedProperties(); DrawRuntimeDebugInfo(t); Repaint(); } private void OnEnable() { m_InstanceRoot = serializedObject.FindProperty("m_InstanceRoot"); m_AudioListener = serializedObject.FindProperty("m_AudioListener"); m_AudioMixer = serializedObject.FindProperty("m_AudioMixer"); m_AudioGroupConfigs = serializedObject.FindProperty("m_AudioGroupConfigs"); } private void CreateDefaultConfigAsset() { AudioGroupConfigCollection asset = ScriptableObject.CreateInstance(); asset.EnsureDefaults(); string path = EditorUtility.SaveFilePanelInProject("创建音频分组配置", "AudioGroupConfigs", "asset", "请选择保存路径"); if (string.IsNullOrEmpty(path)) { UnityEngine.Object.DestroyImmediate(asset); return; } AssetDatabase.CreateAsset(asset, path); AssetDatabase.SaveAssets(); AssetDatabase.Refresh(); m_AudioGroupConfigs.objectReferenceValue = asset; serializedObject.ApplyModifiedProperties(); EditorGUIUtility.PingObject(asset); } private void DrawRuntimeDebugInfo(AudioComponent component) { if (!EditorApplication.isPlaying) { return; } if (!AppServices.TryGet(out IAudioService audioService) || audioService is not IAudioDebugService debugService) { EditorGUILayout.HelpBox("音频服务未初始化。", MessageType.Info); return; } debugService.FillServiceDebugInfo(_serviceInfo); EditorGUILayout.Space(); EditorGUILayout.LabelField("运行时调试", EditorStyles.boldLabel); EditorGUILayout.LabelField("Initialized", _serviceInfo.Initialized.ToString()); EditorGUILayout.LabelField("Unity Audio Disabled", _serviceInfo.UnityAudioDisabled.ToString()); EditorGUILayout.LabelField("Enable", _serviceInfo.Enable.ToString()); EditorGUILayout.LabelField("Volume", _serviceInfo.Volume.ToString("F3")); EditorGUILayout.ObjectField("Listener", _serviceInfo.Listener, typeof(AudioListener), true); EditorGUILayout.ObjectField("Instance Root", _serviceInfo.InstanceRoot, typeof(Transform), true); EditorGUILayout.LabelField("Active Agents", _serviceInfo.ActiveAgentCount.ToString()); EditorGUILayout.LabelField("Handle Capacity", _serviceInfo.HandleCapacity.ToString()); EditorGUILayout.LabelField("Clip Cache", _serviceInfo.ClipCacheCount + " / " + _serviceInfo.ClipCacheCapacity); DrawCategoryDebugInfo(debugService); DrawAgentDebugInfo(debugService); DrawClipCacheDebugInfo(debugService); } private void DrawCategoryDebugInfo(IAudioDebugService debugService) { EditorGUILayout.Space(); EditorGUILayout.LabelField("分类状态", EditorStyles.boldLabel); for (int i = 0; i < debugService.CategoryCount; i++) { if (!debugService.FillCategoryDebugInfo(i, _categoryInfo)) { continue; } EditorGUILayout.LabelField( _categoryInfo.Type.ToString(), "Enabled " + _categoryInfo.Enabled + " | Volume " + _categoryInfo.Volume.ToString("F2") + " | Active " + _categoryInfo.ActiveCount + " | Free " + _categoryInfo.FreeCount + " | Capacity " + _categoryInfo.Capacity); } } private void DrawAgentDebugInfo(IAudioDebugService debugService) { EditorGUILayout.Space(); EditorGUILayout.LabelField("活跃播放", EditorStyles.boldLabel); bool hasActive = false; for (int typeIndex = 0; typeIndex < debugService.CategoryCount; typeIndex++) { if (!debugService.FillCategoryDebugInfo(typeIndex, _categoryInfo)) { continue; } for (int agentIndex = 0; agentIndex < _categoryInfo.Capacity; agentIndex++) { if (!debugService.FillAgentDebugInfo(typeIndex, agentIndex, _agentInfo) || _agentInfo.State == AudioAgentRuntimeState.Free) { continue; } hasActive = true; string clipName = _agentInfo.Clip != null ? _agentInfo.Clip.name : ""; string address = string.IsNullOrEmpty(_agentInfo.Address) ? "" : _agentInfo.Address; EditorGUILayout.LabelField( _agentInfo.Type + "[" + _agentInfo.Index + "]", _agentInfo.State + " | Handle " + _agentInfo.Handle + " | Clip " + clipName + " | Address " + address + " | Vol " + _agentInfo.Volume.ToString("F2") + " | 3D " + _agentInfo.Spatial); } } if (!hasActive) { EditorGUILayout.LabelField("无活跃播放。"); } } private void DrawClipCacheDebugInfo(IAudioDebugService debugService) { EditorGUILayout.Space(); EditorGUILayout.LabelField("Clip 缓存", EditorStyles.boldLabel); AudioClipCacheEntry entry = debugService.FirstClipCacheEntry; if (entry == null) { EditorGUILayout.LabelField("缓存为空。"); return; } while (entry != null) { AudioClipCacheEntry next = entry.AllNext; if (debugService.FillClipCacheDebugInfo(entry, _clipCacheInfo)) { EditorGUILayout.LabelField( _clipCacheInfo.Address, "Ref " + _clipCacheInfo.RefCount + " | Pending " + _clipCacheInfo.PendingCount + " | Loaded " + _clipCacheInfo.IsLoaded + " | Loading " + _clipCacheInfo.Loading + " | Pinned " + _clipCacheInfo.Pinned + " | LRU " + _clipCacheInfo.InLru); } entry = next; } } } }