unity-audio について
Unity のオーディオシステムを扱う開発者向けのリファレンススキルです。ソース、リスナー、ミキサー、空間オーディオの設定とスクリプト例に加え、インポートや再生、リソース管理の注意点をまとめています。
主な機能
- 01AudioSource と AudioListener の解説
- 02Audio Mixer、エフェクト、スナップショットの設定
- 033D 空間オーディオと減衰の設定
- 04音声形式、読み込み、圧縮の説明
- 05再生、フェード、オーディオプールのパターン
- 06よくあるアンチパターンの紹介
活用シーン
- 01シーン内オブジェクトの 3D サウンドを設定
- 02音楽や効果音のミキシングと音量を管理
- 03長い音声の読み込みと圧縮方式を選択
- 04再生の重なりやリソース使用の問題を回避
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nice-wolf-studio/ unity-claude-skills --skill unity-audioインストール後、Claude Code で/unity-audioを入力して読み込まれたか確認します。
同梱ファイルreferences/audio-api.md
詳細
Unity オーディオシステム
オーディオシステムの概要
Unity のオーディオシステムは、完全な 3D 空間サウンド、リアルタイムのミキシングとマスタリング、ミキサーの階層、スナップショット、定義済みのエフェクトを提供します。中核となるアーキテクチャは、ソースとリスナーのモデルに従っています。
- AudioClip -- プロジェクトにインポートされたオーディオデータのコンテナー
- AudioSource -- AudioClip を再生する、GameObject にアタッチされたコンポーネント
- AudioListener -- ソースから音声を受信してスピーカーに出力する、マイクのようなコンポーネント(通常は Main Camera に配置)
- Audio Mixer -- ソースのミキシング、エフェクトの適用、出力のマスタリングを行う中心的なハブ
オブジェクトにアタッチされた AudioSource からサウンドが発生し、AudioListener が受け取ります。Unity はリスナーからのソースの距離と位置を計算し、音量、パン、3D エフェクトを決定します。また、ソースオブジェクトとリスナーオブジェクトの相対速度を使ってドップラー効果もモデル化します。
対応オーディオ形式
| 形式 | 種類 |
|---|---|
.aif、.wav | 非圧縮 |
.mp3、.ogg | 圧縮 |
.xm、.mod、.it、.s3m | トラッカーモジュール |
Unity はモノラル、ステレオ、マルチチャンネルのオーディオアセット(最大 8 チャンネル)に対応しています。
AudioSource と AudioListener
AudioSource
AudioSource コンポーネントはシーン内で AudioClip を再生し、再生動作をカスタマイズするオプションを提供します。主なプロパティは次のとおりです。
| プロパティ | 説明 | デフォルト |
|---|---|---|
clip | 再生する AudioClip | なし |
volume | 再生音量(0.0~1.0) | 1.0 |
pitch | 再生速度/ピッチの倍率 | 1.0 |
loop | クリップの再生完了後にループするかどうか | false |
playOnAwake | GameObject のアクティブ化時に自動再生するかどうか | true |
spatialBlend | 2D(0.0)から 3D(1.0)へのブレンド | 0.0 |
priority | ソースの優先度(0 = 最高、256 = 最低) | 128 |
mute | 再生を停止せずにソースをミュート | false |
outputAudioMixerGroup | ルーティング先のミキサーグループ | なし |
3D サウンド設定
| プロパティ | 説明 |
|---|---|
dopplerLevel | ドップラー効果の強度スケール |
spread | 3D ステレオ/マルチチャンネルの広がり角度(度) |
rolloffMode | 距離に応じた音量の減衰方法(Logarithmic、Linear、Custom) |
minDistance | 音量が最大になる距離 |
maxDistance | 音が聞こえなくなる、または減衰が止まる距離 |
panStereo | ステレオパンの位置(-1 が左、1 が右) |
reverbZoneMix | グローバルリバーブへのミックスレベル |
AudioListener
AudioListener はマイクのようなデバイスとして機能し、シーン内の AudioSource からの入力を受信してスピーカーから出力します。重要なルールは次のとおりです。
- シーンごとに AudioListener は 1 つだけ -- これは厳守が必要な制約です
- デフォルトでは Main Camera に追加されます
- Inspector で設定できるプロパティはありません -- 動作させるには追加するだけです
- 3D の位置オーディオと 2D オーディオ(3D 処理を無視)をどちらも処理します
- 聞こえるすべてのサウンドに Reverb Zones と Audio Effects を適用します
スクリプトから使用できる静的プロパティ:
AudioListener.volume-- マスター音量(0.0~1.0)AudioListener.pause-- オーディオシステム全体を一時停止/再開
AudioClip とインポート設定
読み込みタイプ
| 読み込みタイプ | 動作 | 最適な用途 |
|---|---|---|
| Decompress On Load | 読み込み時にすぐに解凍します。Vorbis では約 10 倍、ADPCM では約 3.5 倍のメモリを使用します | 小さく、頻繁に使用する効果音 |
| Compressed In Memory | メモリ内では圧縮状態を保ち、再生中に解凍します。CPU の負荷がわずかに増加します | 読み込み時の解凍ではメモリ予算を超える、中程度の長さのサウンド |
| Streaming | ディスクからリアルタイムでデコードします。クリップごとに約 200KB のバッファーを使用します | 音楽や環境音トラックなどの長いオーディオ |
圧縮形式
| 形式 | 圧縮率 | 最適な用途 |
|---|---|---|
| PCM | 1:1(非圧縮) | デコード時の CPU コストがかからない、ごく短い効果音 |
| ADPCM | 3.5:1 | ノイズの多いサウンド(足音、衝撃音、武器音) |
| Vorbis/MP3 | 可変(品質スライダー) | 音楽や中程度の長さの効果音 |
インポート設定
| 設定 | 説明 |
|---|---|
| Force To Mono | パッキング前にマルチチャンネルオーディオをモノラルトラックにミックスダウンします |
| Normalize | モノラル変換中にオーディオをノーマライズします |
| Load In Background | メインスレッドをブロックしないよう、クリップを非同期で読み込みます |
| Ambisonic | ファイルに Ambisonic エンコードされた音場が含まれることを示します(XR/360 向け) |
| Preload Audio Data | シーンの読み込み完了時にクリップデータを事前読み込みします(デフォルト:有効) |
| Quality | Vorbis/MP3 形式の圧縮品質スライダー |
| Sample Rate Setting | Preserve、Optimize(自動調整)、または Override(手動で低減) |
オーディオミキサー
オーディオミキサーは、オーディオ出力のミキシング、エフェクト処理、マスタリングを行います。すべてのオーディオミキサーアセットには、デフォルトで Master Group が含まれます。
基本概念
- グループ(バス) -- 音量減衰とピッチ補正を制御する信号チェーンで、階層的に構成されます(例:
Master/SFX/Weapons) - スナップショット -- 実行時に切り替えて異なるムードや雰囲気を作り出せる、保存済みのパラメーター設定
- エフェクト -- グループの信号チェーン内で適用される DSP エフェクト(リバーブ、エコー、EQ など)
- センド/リターン -- あるバスの結果を別のバスに渡し、エフェクト処理を共有します
- ダッキング -- 別のグループの動作に応じて、あるグループの出力を変更します(例:会話の再生中に環境音を小さくする)
- ビュー -- 複雑なミキサーレイアウトを管理するための、さまざまな表示設定
- 公開パラメーター --
SetFloat/GetFloatを介したスクリプト制御に公開されるミキサーパラメーター
注記: Web プラットフォームでは、オーディオミキサーは部分的にしかサポートされていません。
ミキサーのスクリプト制御
using UnityEngine;
using UnityEngine.Audio;
public class MixerController : MonoBehaviour
{
[SerializeField] private AudioMixer mixer;
// Set exposed parameter (must be exposed in the Mixer Inspector)
public void SetVolume(float linear)
{
float dB = Mathf.Log10(Mathf.Max(linear, 0.0001f)) * 20f;
mixer.SetFloat("MasterVolume", dB);
}
// Read exposed parameter (convert dB back to linear)
public float GetVolume()
{
if (mixer.GetFloat("MasterVolume", out float dB))
return Mathf.Pow(10f, dB / 20f);
return 1f;
}
// Reset parameter to snapshot-defined value
public void ResetVolume() => mixer.ClearFloat("MasterVolume");
// Transition to a named snapshot
public void GoToSnapshot(string name, float time)
{
var snap = mixer.FindSnapshot(name);
if (snap != null) snap.TransitionTo(time);
}
// Blend multiple snapshots with weights
public void BlendSnapshots(AudioMixerSnapshot[] snaps, float[] weights, float time)
=> mixer.TransitionToSnapshots(snaps, weights, time);
}
3D 空間オーディオ
基本的な 3D サウンドの設定
完全な 3D 位置指定を行うには、spatialBlend を 1.0 に設定します。Unity の組み込みパンニングは、リスナーからの距離と角度に基づいて、左右の耳への音の寄与を調整します。
空間化プラグイン(HRTF)
高度な 3D オーディオ向けに、Unity は HRTF フィルタリングを備えた空間化プラグインをサポートしています。設定方法:(1) Edit > Project Settings > Audio で空間化プラグインを選択し、(2) 各 AudioSource で Spatialize を有効にし、(3) 必要に応じて spatializePostEffects を設定します。パフォーマンスのヒント:近くのサウンドのみを空間化し、遠くのサウンドには従来のパンニングを使用します。
減衰モード
- Logarithmic -- 現実的な減衰:近距離では大きく、急速に減衰します(デフォルト)
- Linear -- minDistance と maxDistance の間で一定の減衰を行います
- Custom -- ユーザー定義の AnimationCurve
using UnityEngine;
public class SpatialAudioSetup : MonoBehaviour
{
[SerializeField] private AudioSource audioSource;
void Start()
{
// Configure for 3D spatial audio
audioSource.spatialBlend = 1.0f; // Full 3D
audioSource.rolloffMode = AudioRolloffMode.Logarithmic;
audioSource.minDistance = 1f;
audioSource.maxDistance = 50f;
audioSource.dopplerLevel = 1.0f;
audioSource.spread = 0f; // Point source
// Enable spatialization plugin (if configured in Project Settings)
audioSource.spatialize = true;
}
}
よく使われるパターン
効果音の再生
using UnityEngine;
public class SoundEffectPlayer : MonoBehaviour
{
[SerializeField] private AudioSource audioSource;
[SerializeField] private AudioClip shootClip;
[SerializeField] private AudioClip reloadClip;
// Play the assigned clip
public void PlayShoot()
{
audioSource.Play();
}
// PlayOneShot: plays a clip without interrupting the current one
// Supports overlapping sounds and per-call volume scaling
public void PlayReload(float volumeScale = 1.0f)
{
audioSource.PlayOneShot(reloadClip, volumeScale);
}
// Play a clip at a world position (creates a temporary AudioSource)
public void PlayExplosionAt(Vector3 position)
{
AudioSource.PlayClipAtPoint(shootClip, position, 1.0f);
}
// Play with a delay (in seconds)
public void PlayDelayed()
{
audioSource.PlayDelayed(0.5f);
}
// Scheduled playback on DSP timeline (sample-accurate)
public void PlayScheduled()
{
double startTime = AudioSettings.dspTime + 1.0;
audioSource.PlayScheduled(startTime);
}
}
オーディオオブジェクトのプーリング
using UnityEngine;
using System.Collections.Generic;
public class AudioPool : MonoBehaviour
{
[SerializeField] private int poolSize = 10;
private List<AudioSource> pool = new List<AudioSource>();
void Awake()
{
for (int i = 0; i < poolSize; i++)
{
var obj = new GameObject($"PooledAudio_{i}");
obj.transform.SetParent(transform);
var src = obj.AddComponent<AudioSource>();
src.playOnAwake = false;
pool.Add(src);
}
}
public AudioSource Play(AudioClip clip, Vector3 pos, float volume = 1f)
{
var source = pool.Find(s => !s.isPlaying);
if (source == null) return null;
source.transform.position = pos;
source.clip = clip;
source.volume = volume;
source.Play();
return source;
}
}
コルーチンによるオーディオのフェード
using UnityEngine;
using System.Collections;
public class AudioFader : MonoBehaviour
{
[SerializeField] private AudioSource musicSource;
public void CrossFadeTo(AudioClip newClip, float duration)
{
StartCoroutine(CrossFadeCoroutine(newClip, duration));
}
private IEnumerator CrossFadeCoroutine(AudioClip newClip, float duration)
{
float startVol = musicSource.volume;
float half = duration / 2f;
// Fade out
for (float t = 0f; t < half; t += Time.deltaTime)
{ musicSource.volume = Mathf.Lerp(startVol, 0f, t / half); yield return null; }
// Switch clip and fade in
musicSource.clip = newClip;
musicSource.Play();
for (float t = 0f; t < half; t += Time.deltaTime)
{ musicSource.volume = Mathf.Lerp(0f, startVol, t / half); yield return null; }
musicSource.volume = startVol;
}
}
UI スライダーによるミキサー音量の制御
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.UI;
public class VolumeSettings : MonoBehaviour
{
[SerializeField] private AudioMixer mixer;
[SerializeField] private Slider masterSlider;
void Start()
{
masterSlider.value = PlayerPrefs.GetFloat("MasterVol", 1f);
masterSlider.onValueChanged.AddListener(v => SetVolume("MasterVol", v));
}
// Exposed parameter names must match those set in the Audio Mixer Inspector
private void SetVolume(string param, float linear)
{
float dB = linear > 0.0001f ? Mathf.Log10(linear) * 20f : -80f;
mixer.SetFloat(param, dB);
PlayerPrefs.SetFloat(param, linear);
}
}
オーディオの一時停止と再開
// Pause all audio globally
AudioListener.pause = true;
// UI sounds can bypass the global pause
uiSource.ignoreListenerPause = true;
// Resume all audio
AudioListener.pause = false;
// Pause/resume a single source (remembers playback position)
musicSource.Pause();
musicSource.UnPause();
アンチパターン
1. シーン内に複数の AudioListener を配置する
シーン内に存在できる AudioListener は 1 つだけです。副カメラから AudioListener を削除するか、カメラの切り替え時に有効/無効を切り替えてください。
2. 重ねて再生する効果音に Play() を使う
// BAD: Play() restarts the clip, cutting off the previous playback
void OnShoot()
{
audioSource.clip = gunshot;
audioSource.Play(); // Interrupts previous gunshot
}
// GOOD: PlayOneShot allows overlapping instances
void OnShoot()
{
audioSource.PlayOneShot(gunshot, 0.8f);
}
3. 線形値でミキサー音量を設定する
// BAD: Mixer parameters use decibels, not linear 0-1
mixer.SetFloat("MasterVol", 0.5f); // Almost silent, not half volume
// GOOD: Convert linear to logarithmic decibels
float dB = Mathf.Log10(Mathf.Max(value, 0.0001f)) * 20f;
mixer.SetFloat("MasterVol", dB);
4. すべてのオーディオを Decompress On Load で読み込む
大きなオーディオファイル(音楽、会話)を Decompress On Load に設定すると、大量のメモリを消費します(Vorbis では約 10 倍)。長いクリップには Streaming、中程度の長さのクリップには Compressed In Memory を使用してください。
5. 3D サウンドの spatialBlend を設定し忘れる
// BAD: spatialBlend defaults to 0 (2D) -- sound ignores 3D position
AudioSource source = gameObject.AddComponent<AudioSource>();
source.clip = explosionClip;
source.Play(); // Plays at full volume regardless of distance
// GOOD: Set spatialBlend to 1 for 3D positioning
source.spatialBlend = 1.0f;
source.minDistance = 1f;
source.maxDistance = 50f;
source.Play();
6. 頻繁に再生する効果音に PlayClipAtPoint を使う
PlayClipAtPoint は呼び出すたびに一時的な GameObject を作成し、破棄します。銃声や足音など、頻繁に再生するサウンドには、代わりにオーディオプールを使用してください。
7. 3D 効果音で「Force To Mono」を使用しない
3D ソースとして使用するステレオファイルはメモリを無駄に消費します。3D 空間化の際にステレオチャンネルはモノラルに統合されます。3D 効果音では、インポート設定で Force To Mono を有効にしてください。
主要 API クイックリファレンス
| API | 説明 | 備考 |
|---|---|---|
AudioSource.Play() | 割り当てられたクリップを再生します | 再生中の場合は最初から再生します |
AudioSource.PlayOneShot(clip, vol) | 現在の再生を中断せずにクリップを再生します | 重ねて再生できます |
AudioSource.PlayClipAtPoint(clip, pos) | 静的メソッド:ワールド座標で再生します | 一時的な GameObject を作成します |
AudioSource.PlayDelayed(delay) | 秒単位の遅延後に再生します | |
AudioSource.PlayScheduled(time) | DSP 時刻に再生します | サンプル単位で正確にスケジュールできます |
AudioSource.Stop() | 再生を停止します | |
AudioSource.Pause() | 再生を一時停止します | 再生位置を記憶します |
AudioSource.UnPause() | 一時停止した再生を再開します | |
AudioSource.isPlaying | ソースが現在再生中かどうかを示します | 読み取り専用 |
AudioSource.time | 秒単位の再生位置です | 読み書き可能 |
AudioSource.timeSamples | PCM サンプル単位の再生位置です | 読み書き可能 |
AudioListener.volume | 全体のマスターボリュームです | 静的、0.0-1.0 |
AudioListener.pause | すべてのオーディオを一時停止します | 静的 bool |
AudioClip.length | 秒単位のクリップの長さです | 読み取り専用 |
AudioClip.samples | サンプル単位のクリップの長さです | 読み取り専用 |
AudioClip.channels | オーディオチャンネル数です | 読み取り専用 |
AudioClip.frequency | Hz 単位のサンプルレートです | 読み取り専用 |
AudioClip.loadState | 現在の読み込み状態です | 読み取り専用 |
AudioClip.Create(name, len, ch, freq, stream) | 実行時に AudioClip を作成します | |
AudioClip.GetData(data, offset) | サンプルデータを配列に読み込みます | |
AudioClip.SetData(data, offset) | 配列のサンプルデータを書き込みます | |
AudioClip.LoadAudioData() | クリップデータをメモリに読み込みます | |
AudioClip.UnloadAudioData() | クリップデータをメモリからアンロードします | |
AudioMixer.SetFloat(name, val) | 公開パラメーターを設定します | 見つからない場合は false を返します |
AudioMixer.GetFloat(name, out val) | 公開パラメーターの値を取得します | 見つからない場合は false を返します |
AudioMixer.ClearFloat(name) | パラメーターをスナップショットの値にリセットします | |
AudioMixer.FindSnapshot(name) | 名前が完全一致するスナップショットを検索します | AudioMixerSnapshot を返します |
AudioMixer.FindMatchingGroups(path) | パスパターンでグループを検索します | AudioMixerGroup[] を返します |
AudioMixer.TransitionToSnapshots(snaps, weights, time) | 重み付けしてスナップショットをブレンドします | |
AudioMixerSnapshot.TransitionTo(time) | このスナップショットに遷移します |
関連スキル
- unity-foundations -- GameObject、コンポーネント、Transform、Prefab、ScriptableObject
- unity-scripting -- C# スクリプトのパターン、MonoBehaviour のライフサイクル、コルーチン、イベント
- unity-animation -- Animator Controller、Timeline、アニメーションイベント(オーディオとアニメーションの同期に便利です)