社内勉強会でUnityの音にまつわる話をしたので資料をざっくり公開する
ざっくりこんな感じのデモシーン作りましたー pic.twitter.com/KwkZ158rVz
— 青木とと(ˊ꒳ˋ*) (@lycoris102) 2016年12月1日
Unityでの音の取り扱い
概要
- AudioSourceコンポーネント で音 ( AudioClip ) をゲーム世界内で鳴らす
- AudioListenerコンポーネント でゲーム世界内の音を聞き、実機で再生する
AudioClip
- https://docs.unity3d.com/jp/current/Manual/class-AudioClip.html
- https://docs.unity3d.com/jp/current/ScriptReference/AudioClip.html
- 音源のこと
- 以下の拡張子がAudioClipとして取り扱える
- .aif / .wav / .mp3 / .ogg / .xm / .mod / .it /.s3m
- AudioSource経由で再生される
- 主にパフォーマンス絡みで設定を変更することが多い
- モバイルゲームではモノラルを使用する
- iOSではMP3の圧縮を有効にする
- AndroidではVorbisの圧縮を有効にする
- (【Unity】Unite 2016「モバイル端末向けのUnityアプリケーションの最適化実践テクニック」翻訳 より)
AudioSourceコンポーネント
- https://docs.unity3d.com/jp/current/Manual/class-AudioSource.html
- https://docs.unity3d.com/jp/current/ScriptReference/AudioSource.html
- 音源を再生する君
- GameObjectにAudioSourceコンポーネントをアタッチして使用する
- 主にScript経由で任意のタイミングで再生するパターンが多い
- 1つのAudioSourceからは1つの音源のみ再生出来る
- 動的にAudioClipを差し替えることは可能だが、同時に再生できない
- 複数再生したい場合は複数のAudioSourceをアタッチする手法も取れる
AudioListenerコンポーネント
- https://docs.unity3d.com/jp/current/Manual/class-AudioListener.html
- MainCameraにデフォルトでアタッチされた状態なため気付きにくい
- 各シーンで使用できるAudioListenerは1つだけ
AudioSourceコンポーネントで音を制御する
ゲーム開始時(Scene遷移時)に音を再生する
- Inspector上でAudioSourceの PlayOnAwake を有効にする
BGM用に音をループさせる
- Inspector上でAudioSourceの Loop を有効にする
Script経由で音を再生する
- https://docs.unity3d.com/jp/current/ScriptReference/AudioSource.Play.html
AudioSource.Play()
- e.g: ボタンを押したタイミングでBGMを再生する
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Button))]
public class AudioPlayButton : MonoBehaviour
{
public AudioSource AudioSource;
void Start()
{
this.GetComponent<Button>().onClick.AddListener(() => this.AudioSource.Play());
}
}
Script経由で音を停止する
- https://docs.unity3d.com/jp/current/ScriptReference/AudioSource.Stop.html
AudioSource.Stop()
- e.g: ボタンを押したタイミングでBGMを停止する
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Button))]
public class AudioStopButton : MonoBehaviour
{
public AudioSource AudioSource;
void Start()
{
this.GetComponent<Button>().onClick.AddListener(() => this.AudioSource.Stop());
}
}
Script経由で音を一時停止/解除する
- https://docs.unity3d.com/jp/current/ScriptReference/AudioSource.Pause.html
- https://docs.unity3d.com/jp/current/ScriptReference/AudioSource.UnPause.html
-
AudioSource.Pause()
/AudioSource.UnPause()
- e.g) ボタンを押した段階で一時停止 / 離した段階で解除する
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
public class AudioPauseButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
public AudioSource AudioSource;
public Text Text;
public void Start()
{
this.Text.text = "Pause";
}
public void OnPointerDown(PointerEventData eventData)
{
this.AudioSource.Pause();
this.Text.text = "UnPause";
}
public void OnPointerUp(PointerEventData eventData)
{
this.AudioSource.UnPause();
this.Text.text = "Pause";
}
}
Script経由でSEを再生する
- https://docs.unity3d.com/jp/current/ScriptReference/AudioSource.PlayOneShot.html
AudioSource.PlayOneShot(AudioClip)
- 引数にAudioClipを持つ
- 多分同一の音源が複数のアクションによって違う音を鳴らす設計を想定していそう
- 同じ音を重ねて再生出来る
- e.g) ボタンを押した段階でSEを再生する
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
[RequireComponent(typeof(AudioSource))]
public class SEPlayButton : MonoBehaviour, IPointerDownHandler
{
public AudioClip SE;
public void OnPointerDown(PointerEventData eventData)
{
this.GetComponent<AudioSource>().PlayOneShot(SE);
}
}
Script経由で音量を変更する
- https://docs.unity3d.com/jp/current/ScriptReference/AudioSource-volume.html
AudioSource.volume
- e.g) スライダーを動かして音量を変更する
using UnityEngine;
using UnityEngine.UI;
[RequireComponent(typeof(Slider))]
public class AudioVolumeSlider : MonoBehaviour
{
public AudioSource AudioSource;
void Start()
{
this.GetComponent<Slider>().onValueChanged.AddListener(value => this.AudioSource.volume = value);
}
}
Script経由でミュートする
- https://docs.unity3d.com/jp/current/ScriptReference/AudioSource-mute.html
AudioSource.mute
- 元の音量を保持出来る面にて、直接音量を0にするよりアドバンテージがある
- e.g) ボタンを押した段階でミュート / 離した段階で解除する
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
public class AudioMuteButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
public AudioSource AudioSource;
public Text Text;
void Start()
{
this.Text.text = "Mute";
}
public void OnPointerDown(PointerEventData eventData)
{
this.AudioSource.mute = true;
this.Text.text = "UnMute";
}
public void OnPointerUp(PointerEventData eventData)
{
this.AudioSource.mute = false;
this.Text.text = "Mute";
}
}
Unity内で音を管理する
AudioManagerを作って再生管理
- 音が鳴る物にAudioSouce付けて、全シーン毎にAudioListenerを用意して、オーディオファイルを追加する度にAudioClip付けるのが面倒
- 全シーン、どのスクリプトからもBGMとSEを操作出来るようにする
- 以下のようなパターンが多い
- Resources以下に音源ファイルを設置
- シングルトン化してどのシーンからも読み込めるようにする
- AddComponentでBGM/SE用にAudioSourceを用意する
- SEは同時発音用に複数 (同時再生数 or SE個数分) AddComponentすることがある
- 参考
AudioMixerを使ってミックス/マスタリング
- https://docs.unity3d.com/ja/current/Manual/AudioMixer.html
- 複数の音源を再生する際のシチュエーションを整えてくれる君
- AudioMixerを使うと以下のようなことができる
- ミックス (同時発音)
- エフェクト (音に対する効果付け)
- マスタリング (音同士の音量/音圧の調整)
- AudioManagerとも併用可能
- AudioManagerにてAudioGroupも管理してあげる
Unity内で音を加工する
フェードイン/フェードアウト
- AudioSource.volume をScriptで制御する
- Coroutineで処理するなり、Tween系のアセットで処理させるなり
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using DG.Tweening;
// DOTweenをセットアップしている前提
public class AudioFadeButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
public AudioSource AudioSource;
public Text Text;
public float FadeTime = 3.0f;
private float volume;
void Start()
{
this.Text.text = "FadeOut";
}
public void OnPointerDown(PointerEventData eventData)
{
if (!this.AudioSource.isPlaying)
{
return;
}
this.volume = this.AudioSource.volume;
this.AudioSource.DOFade(0.0f, FadeTime).SetEase(Ease.InCubic);
this.Text.text = "FadeIn";
}
public void OnPointerUp(PointerEventData eventData)
{
this.AudioSource.DOFade(volume, FadeTime).SetEase(Ease.InCubic);
this.Text.text = "FadeOut";
}
}
ピッチを変更する
- AudioSource.pitch もしくは AudioMixer.Pitch で変更する
- Pitchが0以下になると逆再生される
エフェクト (フィルター) を掛ける
- AudioMixerを作成する
- 任意のGroupを作成し、AudioSource
- Groupに対して、下部のAddから任意のFilterを掛ける
Unity内で音と同期する( Music.cs )
- https://github.com/geekdrums/MusicEngine
- http://www.slideshare.net/geekdrums/about-musicengine-46632468
- @geekdrums さんの作ったライブラリ
BGMに合わせて要素の大きさを動かす
using UnityEngine;
using DG.Tweening;
public class ChangeScale : MonoBehaviour
{
public float Rate = 1.1f;
public float Time = 0.2f;
private Vector3 baseScale;
void Start()
{
this.baseScale = this.gameObject.transform.localScale;
}
void Update()
{
if (Music.IsPlaying && Music.IsJustChangedBeat())
{
this.gameObject.transform.DOScale(this.baseScale * this.Rate, 0.0f);
this.gameObject.transform.DOScale(this.baseScale, this.Time);
}
}
}
SEをクオンタイズでリズムに合わせて再生する
- リズムに合わせて再生タイミングを自動補正する
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
[RequireComponent(typeof(AudioSource))]
public class SEPlayQuantizeButton : MonoBehaviour, IPointerDownHandler
{
public void OnPointerDown(PointerEventData eventData)
{
Music.QuantizePlay(this.GetComponent<AudioSource>());
}
}
Unity内でイントロループを実装する
- [Unity]誰でも簡単にイントロ付きループBGMを再生するスクリプト
- 【Unity】誰でも簡単にイントロ付きループBGMを再生するスクリプト(2015-11-01繋ぎ改善版)
- AudioSource.PlayScheduled を使っている
- 任意のタイミングでBGMを再生する君
- BPMが同じであれば、アレンジした曲に差し替える用法でも使用できる
3D空間で音を取り扱う
- https://docs.unity3d.com/jp/current/Manual/class-AudioSource.html
- 2Dの場合はListnerとの距離等は考慮されない
- Spatial Blend を3Dに振ることで3DSoundSettingsが有効になる
- 3DSoundSettingsではAudioListenerとの距離と音量の相関やドップラー効果の効き具合が調整出来る
同時再生する上での注意点
- https://docs.unity3d.com/jp/current/Manual/class-AudioSource.html
-
AudioSource.Priority
を適切に設定しないとBGMがSEにかき消される等の懸念がある
参考
-
任天堂サウンドが大事にしていること
- インタラクティブミュージックをやる上でのポイントや事例が分かりやすく書いてある