はじめに
今回はエディタ上でスクリプトからAudioClip
を再生する方法を書きたいと思います。
具体的な利用場面は、EditorWindow
内でボタンを押したら音声を出力したいといった場合とかですかね。
概要
エディタ上で音声を再生するAPI
はUnity
は公式で用意してくれていません。
ただUnityEditor.AudioUtil.dll
に含まれるAudioUtil
クラスをリフレクションを用いて利用することで音声を流す事ができます。
github.com
内部実装はc++
で記述されているので見る事はできませんが、そのC#
ラッパーはUnityCsReference
より見る事ができます。
namespace UnityEditor { [NativeHeader("Editor/Mono/Audio/Bindings/AudioUtil.bindings.h")] [StaticAccessor("AudioUtilScriptBindings", StaticAccessorType.DoubleColon)] internal class AudioUtil { [StaticAccessor("GetAudioManager()", StaticAccessorType.Dot)] extern public static bool resetAllAudioClipPlayCountsOnPlay { get; set; } [StaticAccessor("GetAudioManager()", StaticAccessorType.Dot)] extern public static void PlayPreviewClip([NotNull("NullExceptionObject")] AudioClip clip, int startSample = 0, bool loop = false); [StaticAccessor("GetAudioManager()", StaticAccessorType.Dot)] extern public static void PausePreviewClip(); [StaticAccessor("GetAudioManager()", StaticAccessorType.Dot)] extern public static void ResumePreviewClip(); ... } }
またUnity2020.2
以前はPlayClip
というメソッド名だったそうですが、PlayPreviewClip
に変更されています。
In Unity 2020.2 they changed the method names so "Clip" becomes "PreviewClip", for example "PlayPreviewClip", "IsPreviewClipPlaying", etc.
Reflected AudioUtil class for making audio based Editor Extensions - Unity Forum
やり方
リフレクションを用いてアクセスします。
private static void PlayClip(AudioClip clip) { var audioUtil = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.AudioUtil"); var playClipMethod = audioUtil.GetMethod( "PlayPreviewClip", BindingFlags.Static | BindingFlags.Public, null, new Type[] {typeof(AudioClip), typeof(int), typeof(bool)}, null ); playClipMethod.Invoke(null, new object[] {clip, 0, false}); }
またUnityCsReference
をみてみるとPause
やResume
などもあるようですね。
補足
AudioClip.Create
で生成したAudioClip
をPlayPreviewClip
の引数に渡したところ、音声が流れませんでした。
ただファイルとして出力した後、引数に渡すと一応再生することができました。(AssetDatabase.Refresh()
を忘れず)
注意してください。
補足2
再生終了を検知して一時的に出力したファイルを削除したいことも多いと思います。
そういうときはIsPreviewClipPlaying
を使うと良いでしょう。
private static bool CheckPreviewClipPlaying() { var audioUtil = typeof(UnityEditor.Editor).Assembly.GetType("UnityEditor.AudioUtil"); var checkPreviewClipPlayingMethod = audioUtil.GetMethod( "IsPreviewClipPlaying", BindingFlags.Static | BindingFlags.Public, null, new Type[0], null ); return (bool)checkPreviewClipPlayingMethod.Invoke(null, new object[] {}); }