-
-
Save isaveu/c1879ba31fa8222ae4713b711997f8c2 to your computer and use it in GitHub Desktop.
Unity Audio Manager
This file contains 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
/*手動で変更しないでください*/ | |
public enum AudioKey | |
{ | |
} |
This file contains 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
using MBLDefine; | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Reflection; | |
using System.Text; | |
using UnityEditor; | |
using UnityEngine; | |
using UnityEngine.Audio; | |
/// <summary> | |
/// サウンドを管理する | |
/// </summary> | |
public class SoundManager : SingletonMonoBehaviour<SoundManager> | |
{ | |
private const float MAX_DECIBEL = 0f; | |
private const float MIN_DECIBEL = -80f; | |
[SerializeField] | |
private AudioMixer mixer = null; | |
[SerializeField] | |
private List<string> audioNames = new List<string>(); | |
[SerializeField] | |
private List<AudioSource> audioDatas = new List<AudioSource>(); | |
private SoundSetting soundSetting = new SoundSetting(ExternalFilePath.SOUND_SETTING); | |
/// <summary> | |
/// SEのボリューム | |
/// </summary> | |
public float SE | |
{ | |
get | |
{ return soundSetting.SEVolume; } | |
set | |
{ | |
mixer.SetFloat(AudioMixerParamName.SEVolume.String(), GetDecibelConversion(value)); | |
soundSetting.SEVolume = value; | |
} | |
} | |
/// <summary> | |
/// BGMのボリューム | |
/// </summary> | |
public float BGM | |
{ | |
get { return soundSetting.BGMVolume; } | |
set | |
{ | |
mixer.SetFloat(AudioMixerParamName.BGMVolume.String(), GetDecibelConversion(value)); | |
soundSetting.BGMVolume = value; | |
} | |
} | |
private void Awake() | |
{ | |
try | |
{ | |
LoadSettingFile(); | |
} | |
catch(IOException e) | |
{ | |
Debug.LogWarning(e.Message); | |
soundSetting.SEVolume = 1f; | |
soundSetting.BGMVolume = 1f; | |
} | |
} | |
private void Start() | |
{ | |
SE = soundSetting.SEVolume; | |
BGM = soundSetting.BGMVolume; | |
} | |
/// <summary> | |
/// サウンドを再生する | |
/// </summary> | |
/// <param name="key">サウンドのキー</param> | |
public void Play(AudioKey key) | |
{ | |
audioDatas[(int)key].Play(); | |
} | |
/// <summary> | |
/// サウンドを再生する | |
/// </summary> | |
/// <param name="key">サウンドのキー</param> | |
public void Play(string key) | |
{ | |
Play(ConvertAudioKey(key)); | |
} | |
/// <summary> | |
/// サウンドを再生する | |
/// 同一キーのサウンドを同時に複数鳴らすことが可能 | |
/// </summary> | |
/// <param name="key">サウンドのキー</param> | |
public void PlayOneShot(AudioKey key) | |
{ | |
audioDatas[(int)key].PlayOneShot(audioDatas[(int)key].clip); | |
} | |
/// <summary> | |
/// サウンドを再生する | |
/// 同一キーのサウンドを同時に複数鳴らすことが可能 | |
/// </summary> | |
/// <param name="key">サウンドのキー</param> | |
public void PlayOneShot(string key) | |
{ | |
PlayOneShot(ConvertAudioKey(key)); | |
} | |
/// <summary> | |
/// 再生を停止する | |
/// </summary> | |
/// <param name="key">サウンドのキー</param> | |
public void Stop(AudioKey key) | |
{ | |
audioDatas[(int)key].Stop(); | |
} | |
/// <summary> | |
/// 再生を停止する | |
/// </summary> | |
/// <param name="key">サウンドのキー</param> | |
public void Stop(string key) | |
{ | |
Stop(ConvertAudioKey(key)); | |
} | |
/// <summary> | |
/// 設定ファイルを読み込む | |
/// </summary> | |
public void LoadSettingFile() | |
{ | |
soundSetting.LoadSettingFile(); | |
} | |
/// <summary> | |
/// 設定ファイルを保存する | |
/// </summary> | |
public void SaveSettingFile() | |
{ | |
soundSetting.SaveSettingFile(); | |
} | |
/// <summary> | |
/// 文字列をAudioKeyに変換する | |
/// </summary> | |
/// <param name="key">AudioKeyに変換する文字列</param> | |
/// <returns>該当するAudioKey</returns> | |
private AudioKey ConvertAudioKey(string key) | |
{ | |
var keyIndex = audioNames.IndexOf(key); | |
if(keyIndex < 0) | |
throw new Exception(key + "のAudioKeyへの変換に失敗しました"); | |
return (AudioKey)keyIndex; | |
} | |
/// <summary> | |
/// デシベル変換 | |
/// </summary> | |
private float DecibelConversion(float volume) | |
{ | |
return 20f * Mathf.Log10(volume); | |
} | |
/// <summary> | |
/// デシベル変換後の値を得る | |
/// 変換後の値は適切な値を取るようClampされる | |
/// </summary> | |
private float GetDecibelConversion(float value) | |
{ | |
return Mathf.Clamp(DecibelConversion(value), MIN_DECIBEL, MAX_DECIBEL); | |
} | |
#region CustomInspector | |
#if UNITY_EDITOR | |
[CustomEditor(typeof(SoundManager))] | |
private class SoundManagetInspector : Editor | |
{ | |
private SoundManager soundManager; | |
private int selectAudioSourceIndex; | |
private string newAudioDataName = string.Empty; | |
private List<bool> foldSoundDatas = new List<bool>(); | |
private string outputScriptPath = string.Empty; | |
private const string SCRIPT_FILE_NAME = "AudioSourceKeyMap.cs"; | |
private const string SCRIPT_FILE_CONTENT = | |
@" | |
/*手動で変更しないでください*/ | |
public enum AudioKey | |
{ | |
[CONTENT] | |
}"; | |
public override void OnInspectorGUI() | |
{ | |
soundManager = target as SoundManager; | |
soundManager.mixer = EditorGUILayout.ObjectField("AudioMixer", soundManager.mixer, typeof(AudioMixer), false) as AudioMixer; | |
EditorGUILayout.Separator(); | |
#region AudioData | |
for(int i = 0; i < soundManager.audioDatas.Count; ++i) | |
{ | |
if(foldSoundDatas.Count < i + 1) | |
foldSoundDatas.Add(false); | |
if(foldSoundDatas[i] = EditorGUILayout.Foldout(foldSoundDatas[i], soundManager.audioNames[i])) | |
{ | |
EditorGUILayout.BeginVertical("box"); | |
EditorGUILayout.BeginHorizontal(); | |
//再生ボタン表示 | |
if(soundManager.audioDatas[i] != null && soundManager.audioDatas[i].isPlaying) | |
{ | |
if(GUILayout.Button("■")) | |
{ | |
soundManager.audioDatas[i].Stop(); | |
} | |
} | |
else if(GUILayout.Button("▶")) | |
{ | |
soundManager.audioDatas[i].Play(); | |
} | |
EditorGUILayout.EndHorizontal(); | |
soundManager.audioDatas[i].clip = EditorGUILayout.ObjectField("AudioClip", soundManager.audioDatas[i].clip, typeof(AudioClip), false) as AudioClip; | |
soundManager.audioDatas[i].loop = EditorGUILayout.Toggle("Loop", soundManager.audioDatas[i].loop); | |
soundManager.audioDatas[i].playOnAwake = EditorGUILayout.Toggle("PlayOnAwake", soundManager.audioDatas[i].playOnAwake); | |
soundManager.audioDatas[i].volume = EditorGUILayout.Slider("Volume", soundManager.audioDatas[i].volume, 0, 1); | |
soundManager.audioDatas[i].pitch = EditorGUILayout.Slider("Pitch", soundManager.audioDatas[i].pitch, -3, 3); | |
soundManager.audioDatas[i].bypassEffects = EditorGUILayout.Toggle("BypassEffects", soundManager.audioDatas[i].bypassEffects); | |
soundManager.audioDatas[i].bypassListenerEffects = EditorGUILayout.Toggle("BypassListenerEffects", soundManager.audioDatas[i].bypassListenerEffects); | |
soundManager.audioDatas[i].bypassReverbZones = EditorGUILayout.Toggle("BypassReverbZone", soundManager.audioDatas[i].bypassReverbZones); | |
soundManager.audioDatas[i].reverbZoneMix = EditorGUILayout.Slider("ReverbZoneMix", soundManager.audioDatas[i].reverbZoneMix, 0, 1.1f); | |
soundManager.audioDatas[i].spatialBlend = EditorGUILayout.Slider("SpatialBlend", soundManager.audioDatas[i].spatialBlend, 0, 1); | |
soundManager.audioDatas[i].mute = EditorGUILayout.Toggle("Mute", soundManager.audioDatas[i].mute); | |
soundManager.audioDatas[i].outputAudioMixerGroup = EditorGUILayout.ObjectField("OutPut", soundManager.audioDatas[i].outputAudioMixerGroup, typeof(AudioMixerGroup), false) as AudioMixerGroup; | |
if(soundManager.audioDatas[i].outputAudioMixerGroup == null) | |
{ | |
EditorGUILayout.HelpBox("Outputが設定されていないオーディオは音量の一括設定等が適用できません", MessageType.Error); | |
} | |
EditorGUILayout.EndVertical(); | |
} | |
} | |
#endregion AudioData | |
#region Add/Remove Button | |
EditorGUILayout.BeginHorizontal(); | |
newAudioDataName = EditorGUILayout.TextField(newAudioDataName); | |
if(GUILayout.Button("追加")) | |
{ | |
if(soundManager.audioNames.Contains(newAudioDataName) || string.IsNullOrEmpty(newAudioDataName)) | |
{ | |
GUIContent content = new GUIContent("既にKeyが存在するか、Keyが空です"); | |
EditorWindow.focusedWindow.ShowNotification(content); | |
} | |
else | |
{ | |
soundManager.audioNames.Add(newAudioDataName); | |
var newAudioSource = soundManager.gameObject.AddComponent<AudioSource>(); | |
newAudioSource.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector; | |
soundManager.audioDatas.Add(newAudioSource); | |
} | |
newAudioDataName = string.Empty; | |
} | |
EditorGUILayout.Space(); | |
selectAudioSourceIndex = EditorGUILayout.Popup(selectAudioSourceIndex, soundManager.audioNames.ToArray()); | |
if(GUILayout.Button("削除")) | |
{ | |
if(soundManager.audioNames.Count > selectAudioSourceIndex) | |
{ | |
DestroyImmediate(soundManager.audioDatas[selectAudioSourceIndex]); | |
soundManager.audioNames.RemoveAt(selectAudioSourceIndex); | |
soundManager.audioDatas.RemoveAt(selectAudioSourceIndex); | |
foldSoundDatas.RemoveAt(selectAudioSourceIndex); | |
} | |
} | |
EditorGUILayout.EndHorizontal(); | |
DebugEditorScript(); | |
#endregion Add/Remove Button | |
EditorGUILayout.Space(); | |
#region CreateScriptFile | |
if(GUILayout.Button("適用")) | |
{ | |
outputScriptPath = Directory.GetFiles(Directory.GetCurrentDirectory(), "SoundManager.cs", SearchOption.AllDirectories).FirstOrDefault(); | |
if(string.IsNullOrEmpty(outputScriptPath)) | |
outputScriptPath = Path.Combine(Directory.GetCurrentDirectory(), "Assets"); | |
var fullPath = Path.Combine(Directory.GetParent(outputScriptPath).FullName, SCRIPT_FILE_NAME); | |
//Assets以下でなければエラーポップアップ | |
if(!fullPath.Contains(Path.Combine(Directory.GetCurrentDirectory(), "Assets"))) | |
Debug.LogError("スクリプトはAssets以下に配置してください : " + fullPath); | |
//ファイルが保存できる場合 | |
else | |
using(var writer = new StreamWriter(fullPath, false)) | |
{ | |
StringBuilder sb = new StringBuilder(); | |
foreach(var key in soundManager.audioNames) | |
sb.Append("\t" + key + ",\r\n"); | |
var innerContent = sb.ToString(); | |
var content = SCRIPT_FILE_CONTENT.Replace("[CONTENT]", innerContent); | |
writer.Write(content); | |
AssetDatabase.Refresh(); | |
Debug.Log(string.Format("保存しました : {0}", fullPath)); | |
} | |
} | |
#endregion CreateScriptFile | |
EditorUtility.SetDirty(soundManager); | |
} | |
/// <summary> | |
/// エディタスクリプトデバッグ用機能 | |
/// </summary> | |
[System.Diagnostics.Conditional("DEBUG")] | |
private void DebugEditorScript() | |
{ | |
EditorGUILayout.Space(); | |
EditorGUILayout.BeginHorizontal(); | |
if(GUILayout.Button("AudioSoueceの表示")) | |
{ | |
var allAudioSource = soundManager.GetComponents<AudioSource>(); | |
foreach(var data in allAudioSource) | |
data.hideFlags = HideFlags.None | HideFlags.NotEditable; | |
} | |
if(GUILayout.Button("AudioSourceの非表示")) | |
{ | |
var allAudioSource = soundManager.GetComponents<AudioSource>(); | |
foreach(var data in allAudioSource) | |
data.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector | HideFlags.NotEditable; | |
} | |
if(GUILayout.Button("AudioSourceのクリア")) | |
{ | |
var allAudioSource = soundManager.GetComponents<AudioSource>(); | |
//非表示中は削除できない | |
if(allAudioSource.Any(s => (s.hideFlags & HideFlags.HideInInspector) != HideFlags.HideInInspector)) | |
{ | |
GUIContent content = new GUIContent("AudioSourceを非表示にしてから実行してください"); | |
EditorWindow.focusedWindow.ShowNotification(content); | |
} | |
else | |
{ | |
for(int i = 0; i < allAudioSource.Count(); ++i) | |
DestroyImmediate(allAudioSource[i]); | |
soundManager.audioDatas.Clear(); | |
soundManager.audioNames.Clear(); | |
foldSoundDatas.Clear(); | |
} | |
} | |
EditorGUILayout.EndHorizontal(); | |
} | |
} | |
#endif | |
#endregion CustomInspector | |
} |
This file contains 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
using System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Runtime.CompilerServices; | |
using UnityEngine; | |
[assembly: InternalsVisibleTo("UnitTest")] | |
/// <summary> | |
/// MBLで定義する定数を扱う | |
/// </summary> | |
namespace MBLDefine | |
{ | |
/// <summary> | |
/// 外部ファイルへの参照に必要なパス群 | |
/// </summary> | |
internal struct ExternalFilePath | |
{ | |
internal const string KEY_CONFIG = "keyconf.dat"; | |
internal const string SOUND_SETTING = "soundset.dat"; | |
internal const string EVENT = "eventdat.xml"; | |
internal const string EVENT_SCHEMA = "eventdat.xsd"; | |
//TODO:セーブデータ等追加 | |
} | |
/// <summary> | |
/// Resoures内のリソースへのパス | |
/// </summary> | |
internal struct ResourcePath | |
{ | |
internal const string GLOBAL_SCRIPTS = "Prefab/System/GlobalScripts"; | |
internal const string MENU = "Prefab/UI/MenuCanvas"; | |
internal const string CHAT = "Prefab/UI/ChatCanvas"; | |
} | |
/// <summary> | |
/// 入力値の基底クラス | |
/// </summary> | |
public class InputValue | |
{ | |
public readonly string String; | |
protected InputValue(string name) | |
{ | |
String = name; | |
} | |
} | |
/// <summary> | |
/// 使用するキーを表すクラス | |
/// </summary> | |
public sealed class Key : InputValue | |
{ | |
public readonly List<KeyCode> DefaultKeyCode; | |
public readonly static List<Key> AllKeyData = new List<Key>(); | |
private Key(string keyName, List<KeyCode> defaultKeyCode) | |
: base(keyName) | |
{ | |
DefaultKeyCode = defaultKeyCode; | |
AllKeyData.Add(this); | |
} | |
public override string ToString() | |
{ | |
return String; | |
} | |
public static readonly Key Action = new Key("Action", new List<KeyCode> { KeyCode.Z }); | |
public static readonly Key Jump = new Key("Jump", new List<KeyCode> { KeyCode.Space }); | |
public static readonly Key Balloon = new Key("Balloon", new List<KeyCode> { KeyCode.X }); | |
public static readonly Key Squat = new Key("Squat", new List<KeyCode> { KeyCode.C }); | |
public static readonly Key Menu = new Key("Menu", new List<KeyCode> { KeyCode.Escape }); | |
} | |
/// <summary> | |
/// 使用する軸入力を表すクラス | |
/// </summary> | |
public sealed class Axis : InputValue | |
{ | |
public readonly static List<Axis> AllAxisData = new List<Axis>(); | |
private Axis(string AxisName) | |
: base(AxisName) | |
{ | |
AllAxisData.Add(this); | |
} | |
public override string ToString() | |
{ | |
return String; | |
} | |
public static Axis Horizontal = new Axis("Horizontal"); | |
public static Axis Vertical = new Axis("Vertical"); | |
} | |
/// <summary> | |
/// アニメーションパラメーターの型を表すクラス | |
/// </summary> | |
public enum AnimationParamType | |
{ | |
Float, | |
Int, | |
Bool, | |
Trigger | |
} | |
/// <summary> | |
/// アニメーションパラメータの基底クラス | |
/// </summary> | |
internal class AnimationParam | |
{ | |
public readonly string String; | |
public readonly AnimationParamType ParamType; | |
protected AnimationParam(string stateName, AnimationParamType type) | |
{ | |
String = stateName; | |
ParamType = type; | |
} | |
public override string ToString() | |
{ | |
return String; | |
} | |
} | |
/// <summary> | |
/// プレイヤーのアニメーションパラメーター | |
/// </summary> | |
internal sealed class PlayerAnimationParam : AnimationParam | |
{ | |
private PlayerAnimationParam(string stateName, AnimationParamType type) | |
: base(stateName, type) | |
{ | |
} | |
public static PlayerAnimationParam Walk = new PlayerAnimationParam("Walk", AnimationParamType.Bool); | |
public static PlayerAnimationParam JumpStart = new PlayerAnimationParam("JumpStart", AnimationParamType.Trigger); | |
public static PlayerAnimationParam JumpEnd = new PlayerAnimationParam("JumpEnd", AnimationParamType.Trigger); | |
public static PlayerAnimationParam TakeObject = new PlayerAnimationParam("TakeObject", AnimationParamType.Bool); | |
public static PlayerAnimationParam TakeBalloon = new PlayerAnimationParam("TakeBalloon", AnimationParamType.Bool); | |
public static PlayerAnimationParam Squat = new PlayerAnimationParam("Squat", AnimationParamType.Bool); | |
public static PlayerAnimationParam Put = new PlayerAnimationParam("Put", AnimationParamType.Trigger); | |
} | |
/// <summary> | |
/// 入力イベントグループ名 | |
/// </summary> | |
internal enum InputEventGroupName | |
{ | |
/// <summary> | |
/// プレイヤー操作イベント | |
/// </summary> | |
Player, | |
/// <summary> | |
/// メニュー表示・非表示イベント | |
/// </summary> | |
SwitchMenu, | |
/// <summary> | |
/// メニュー内操作イベント | |
/// </summary> | |
InMenu, | |
} | |
internal enum AudioMixerParamName | |
{ | |
BGMVolume, | |
SEVolume, | |
} | |
/// <summary> | |
/// 列挙型の拡張メソッドを保有する | |
/// </summary> | |
internal static class ExtensionEnum | |
{ | |
public static string String(this InputEventGroupName group) | |
{ | |
return group.ToString(); | |
} | |
public static string String(this AudioMixerParamName param) | |
{ | |
return param.ToString(); | |
} | |
} | |
} |
This file contains 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
using LitJson; | |
using MBLDefine; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Text; | |
using UnityEngine; | |
/// <summary> | |
/// サウンド設定の情報を取り扱うクラス | |
/// </summary> | |
public class SoundSetting | |
{ | |
private const string SE = "SE"; | |
private const string BGM = "BGM"; | |
private Dictionary<string, double> data = new Dictionary<string, double>(); | |
private readonly string filePath; | |
/// <summary> | |
/// SEのVolumeへのアクセサー | |
/// </summary> | |
public float SEVolume | |
{ | |
get { return (float)data[SE]; } | |
set { data[SE] = value; } | |
} | |
/// <summary> | |
/// BGMのVolumeへのアクセサー | |
/// </summary> | |
public float BGMVolume | |
{ | |
get { return (float)data[BGM]; } | |
set { data[BGM] = value; } | |
} | |
/// <summary> | |
/// サウンド設定を扱うクラスを生成する | |
/// </summary> | |
/// <param name="filePath"></param> | |
public SoundSetting(string filePath) | |
{ | |
this.filePath = filePath; | |
data.Add(SE, 0); | |
data.Add(BGM, 0); | |
} | |
public void LoadSettingFile() | |
{ | |
//TODO:復号処理 | |
using(TextReader tr = new StreamReader(filePath, Encoding.UTF8)) | |
data = JsonMapper.ToObject<Dictionary<string, double>>(tr); | |
} | |
/// <summary> | |
/// 設定を保存する | |
/// </summary> | |
public void SaveSettingFile() | |
{ | |
//TODO:暗号化処理 | |
using(TextWriter tw = new StreamWriter(filePath, false, Encoding.UTF8)) | |
tw.Write(JsonMapper.ToJson(data)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment