【Unity】Audioの基本と扱いについて

今回はAudioの扱い方です。 3Dサウンドについては触れず、社内で扱う事の多い2Dサウンドを前提にして書いていきます。

こんにちは、ソーシャルゲーム事業部所属エンジニアのぴーちんです!!宜しくお願いしますヾ(@⌒ー⌒@)ノ

この記事はカヤックUnityアドベントカレンダー2016の17日目の記事になります。

Audioの扱いについて

Unityで音を鳴らす仕組みの基本

Unityの音は AudioClip, AudioSource, AudioListener, AudioMixer などのComponentによって鳴らされています。

AudioClipをAudioSourceが再生し、AudioListnerがそれを受信して、物理的なスピーカーなどを通じて私達へ音を届けてくれます。 この関係は公式マニュアルのAudioOverViewで詳しく説明されています。

また、AudioListnerが音を受信する前にAudioMixerを介する事で、音にエフェクトをかけたり音量を調整したりする事が可能です。 この関係は公式マニュアルのAudioMixerOverviewで詳しく説明されています。

AudioMixerの他にも、AudioSourceやAudioListnerが付いてるGameObjectに AudioFIlter 関連のComponentを付けて音を調整する方法もあります。

Unityで扱える音声フォーマットの種類について

Unityでは以下のフォーマットがサポートされています。 理由は後述しますが、 社内では基本的に .wav などの非圧縮フォーマットを扱う場合が多いです。

https://docs.unity3d.com/ja/current/Manual/AudioFiles.html

AudioFileとAudioFormatの関係

UnityにimpotしたAudioFile( .mp3 , .wav など)は、そのままゲームに使われるわけではありません。 UnityへimportしたAudioFileは AudioClip としてUnityに取り込まれ、ゲーム内で扱われるサウンドはAudioClipのInspectorで設定されたものが再生される事になります。

f:id:pchin:20161216231112p:plain

なので、元のオーディオファイルがそのまま再生されるわけでなく、インポート時に指定形式に変換されたサウンドがUnity内で扱われる事になります。

この仕組みについては10日目の『Texture File と Texture Formatの関係』でも触れられていますので、詳細は割愛します。

音声ファイルの品質について

.ogg.mp3 などの非可逆圧縮されるフォーマットをUnityへimportする際の注意点があります。 現時点でUnityはデフォルトで非可逆圧縮フォーマットの Vorbis 形式(.ogg) に設定されてしまいます。 非可逆圧縮形式の音声を再圧縮してしまう場合、再生時の劣化が多くなってしまいます。

どうやらデフォルトの圧縮設定はUnity5から変更された様です。 詳しくは公式マニュアルを参照してください。

一方で .wavaiff などの無圧縮フォーマットをUnityへimportする際には、上記の様な心配事はありません。 AudioClipのInspectorの設定次第で、生データのまま扱う事も非可逆圧縮形式に設定する事も可能です。

基本的に社内のモバイルゲーム開発ではBGM/SE両方で .wav を使用する場合が多いです。 理由としては、Unityへimport後に圧縮設定が行えるので、わざわざ圧縮されたファイルをUnityへimportする必要が無いからです。

AssetPostprocessor

先程はAudioClipのInspectorから、圧縮の設定や読み込み方法を設定可能な事について触れました。 基本的にチームで開発する際にAudioClipの設定は、設定漏れやミスをを避ける為に自動で処理します。 UnityにはAssetの変更時などイベントをHookする機能が提供されています。

AudioのimportをHookするには OnPostprocessAudioを使います。

設定例

using UnityEditor;
using UnityEngine;

public class AssetPostprocessAudio : AssetPostprocessor
{
    private void OnPreprocessAudio()
    {
        var importer = assetImporter as AudioImporter;

        importer.forceToMono = false;
        importer.loadInBackground = false;
        importer.preloadAudioData = true;

        var settings = new AudioImporterSampleSettings()
        {
            compressionFormat = AudioCompressionFormat.MP3, // mp3に圧縮します
            loadType = AudioClipLoadType.CompressedInMemory, // 圧縮された状態でメモリに保持されます
            quality = 0.15f, // 品質の設定
            sampleRateOverride = 44100, // AudioClipのsamplingRateを44,1kHzに設定 ※1
        };
        importer.SetOverrideSampleSettings("iOS", settings);
        importer.SetOverrideSampleSettings("Android", settings);
    }
}

AudioClipのsamplingRateを44,1kHzに設定 ※1

AudioManagerから音出力時のSamplingRateを指定出来るので、もしUnityへimportした音データのSamplingRateがそこで設定された値以上の場合には無駄になるので、import時に調整してあげましょう。

AudioManagerから音出力時のSamplingRateを指定出来る

先ほど紹介したのはAudioClipのSamplingRateについてですが、音を出力する際のSamplingRateをグローバルに設定する事が可能です。 それらを以下で紹介します。

AudioManager

UnityEditorのEdit->ProjectSettings->Audioから開ける設定画面です。

ここでのSamplingRateの設定が0の場合に、iOS/Androidだとデフォルトで出力時のSamplingRateが24kHzになってしまいます。 困る場合にはゲームに適したSamplingRateを設定しておきましょう。 社内ではプロジェクトによりますが、44,1kHzに設定しておく事が多いです。

このTipsはUnityの公式ブログにて紹介されています。

その他の詳しい情報は公式マニュアルをご覧ください

AudioSettings

Unity5から AudioSettingsというランタイムのみに適用される、グローバルな設定を管理可能なAPIが提供されています。

使うケースですが、ゲームの設定画面にて AudioConfiguration の設定項目をユーザーに設定させて、その場で設定を反映する。

具体的なコードを交えた使用例はAudioSettings.ResetのScriptReferenceに例が記載されてるので、割愛します。

SEとBGMの音の鳴らし方の違い

ゲームでは基本的にSE/BGMの2種類の音を扱います。 この2種類の音を再生する場合の違いを紹介します。

BGM

BGMは基本的に『途切れずに鳴らせる』設計にするべきです。 なので、BGMを鳴らす専用のAudioSourceを最低でも2つ用意します。 理由としては、ゲームの特性によりますが、多くのゲームでBGMをクロスフェードさせる場合が多いです。

コード例としては、以下の様な感じになります。 最近はDOTweenだけで簡単なCrossFade処理なら書ける様です、便利ですね。

ちなみに DOTweenについては『【Unity】Tween アニメーション(DOTween)の話』で紹介されていますので、合わせてお読み下さい。

using UnityEngine;
using DG.Tweening;

public class BGMCrossFadeSample : MonoBehaviour
{
    // BGM再生用のAudioSourceを2つ用意
    [SerializeField]
    private AudioSource _source0;

    [SerializeField]
    private AudioSource _source1;


    public void CrossFade(float maxVolume, float fadingTime)
    {
        var fadeInSource =
            _source0.isPlaying ?
            _source1 :
            _source0;

        var fadeOutSource =
            _source0.isPlaying ?
            _source0 :
            _source1;

        fadeInSource.Play();
        fadeInSource.DOKill();
        fadeInSource.DOFade(maxVolume, fadingTime);

        fadeOutSource.DOKill();
        fadeOutSource.DOFade(0, fadingTime);
    }

}

SE

SEはBGMと違い、継続して鳴らさなくて良いです。 しかしSEは『同時再生可能』な様に設計しなければいけません。 それはゲームの特性によって変わるので固定でAudioSourceを用意するも良いですし、可変にAudioSourceのinstanceを増やす仕組みを作るという選択肢もあります。

コード例は少し大変だったので割愛します。インターネットで検索すると書いてる人が多いので参考にして下さい。

AudioMixer

Unity5から音をMixingする為のEditorが公式でサポートされました。 サウンドのミキシング、エフェクト、マスタリングなどの機能があります。

詳しくはUnityのマニュアル動画のチュートリアルを見ると良いでしょう。

(ちなみにこの記事の時点では、まだ弊社では本格的に使った事例はありません)

調整した設定は .mixer ファイルとして保存できるので、サウンドの調整をディレクターなどと分業する事がしやすくなります。 .mixer ファイルにはゲーム内で扱うグローバルな設定をするのが良さそうです。 特別な設定が必要な時はScriptなどで済ますのが良さそうです。

使用例

  • ストーリー画面でBGMとキャラボイスが混在する場合、ボイスの音が発生されたタイミングではBGMの音量を下げたい時(Ducking)
  • 洞窟にキャラクターが歩いてる時に音が響く様にしたい時(Reverb)

おわりに

明日はローカルデータの保存についての記事になります。 担当はしみーさんになります。 お楽しみに。