スポンサーリンク
エラー・トラブルシューティング

Unityで音がズレる原因と対策|Audio同期問題を完全解決

エラー・トラブルシューティング
  1. はじめに
  2. まず最初に確認すべき5つのポイント
  3. Unityで音がズレる本質的な理由
    1. なぜ音だけズレるのか
    2. フレーム依存とDSP時間の違い
    3. どの程度のズレなら正常か
  4. よくある原因5選と解決方法
    1. Updateでタイミングを制御している
    2. AudioSource.Play()を使っている
    3. BGMと処理を別タイミングで開始している
    4. 処理負荷によるフレーム落ち
    5. オーディオ設定(バッファ)の問題
  5. 正しい音同期の実装方法
    1. 音は「未来の時間を予約する」
    2. 基本の実装コード
    3. なぜこの方法でズレなくなるのか
    4. BGMと演出を完全に同期させる方法
    5. よくある失敗パターン
    6. 一歩進んだ使い方(中級者向け)
  6. すぐ確認できる診断チェックリスト
    1. 基本チェック
    2. 挙動チェック
    3. 環境チェック
    4. 判断の目安
  7. よくある誤解と注意点
    1. Play()でも問題ないという思い込み
    2. PCならズレないという誤解
    3. 音ズレは処理落ちだけが原因ではない
    4. Updateで補正すれば解決できるという考え
    5. 音と見た目は同じ時間で動いているという誤解
  8. 実務で使う判断基準と検証方法
    1. 音ズレを正しく確認する方法
    2. ズレの体感判断基準
    3. 検証に使う機材
    4. よくある失敗パターン
    5. 実務でのおすすめ運用
  9. 時間管理の理解を深める
    1. UpdateとFixedUpdateの違い
    2. Time系とDSP時間の違い
    3. なぜ時間を分けて考える必要があるのか
    4. 実務でのシンプルな判断ルール
  10. まとめ
  11. よくある質問(FAQ)
    1. 関連記事:

はじめに

音を再生しているはずなのに、なぜか微妙にズレる…。
Unityでオーディオを扱っていると、一度はこの問題にぶつかることがあります。

例えばこんな経験はありませんか?

  • BGMに合わせて演出を入れたのに、タイミングが合わない
  • SEを同時に鳴らしているのに、微妙にズレる
  • リズムゲームを作ったら判定がズレてしまう
  • PCでは問題ないのに、スマホでズレる

この問題、実は「設定ミス」ではなく、Unityの仕組みそのものが原因になっているケースがとても多いです。

なんとなく調整しても直らなかったり、環境によってズレたりするのはそのためです。

ここで重要なのは、「音は他の処理と同じ扱いではダメ」という点です。

Unityの音は、見た目の処理とはまったく別の仕組みで動いています。
この違いを理解しないまま実装すると、どれだけ頑張ってもズレ続けます。

逆に言えば、正しい仕組みを理解してしまえば、
音ズレはほぼ確実にコントロールできる問題です。

ここでは次のポイントを中心に解説していきます。

  • 音がズレる本当の原因
  • ズレを防ぐための正しい同期方法
  • どの程度のズレなら問題ないのかという判断基準

「なんとなく直す」ではなく、「仕組みで解決する」状態を目指していきましょう🙂


まず最初に確認すべき5つのポイント

音ズレの原因を探すときは、細かい調整に入る前に、まず大きな原因を先に潰すのが近道です。
ここを飛ばしてしまうと、後で「そこだったのか…」となりがちです。私も最初の頃はよくやりました。

先に結論を書くと、次の5つを確認すると原因をかなり絞れます。

  • Updateで音のタイミングを合わせていないか
  • AudioSource.Play()で厳密な同期をしようとしていないか
  • フレームレートに依存した処理になっていないか
  • 重い処理のせいで一時的にFPSが落ちていないか
  • AudioSettings.dspTimeを使わずに実装していないか

この5つのうち、特に優先して見てほしいのは次の3つです。

  1. Updateで同期していないか
  2. Play()をそのまま使っていないか
  3. dspTimeを使っているか

なぜこの3つが大事かというと、音ズレの多くは「音の問題」ではなく「時間の扱い方の問題」だからです。

例えば、見た目の演出をUpdateで動かしながら、音も同じ感覚でPlay()しているとします。
この方法は一見ふつうに見えますが、実際には画面の更新タイミングと音の再生タイミングが別物なので、少しずつズレたり、環境によって結果が変わったりします。

逆に言うと、ここが整理できていれば、かなりの確率で解決の方向が見えてきます。

確認ポイント起きやすい症状優先度
Updateで同期している徐々にズレる、端末で差が出る
Play()を使っている同時再生のはずが微妙にズレる
dspTimeを使っていない厳密な同期ができない
FPSが落ちている重い場面だけズレる
フレーム依存の実装動くたびに結果が安定しない

もし今すぐ確認するなら、順番はこうです。

  1. 再生タイミングをUpdateで決めていないか見る
  2. AudioSource.Play()だけで同期しようとしていないか見る
  3. AudioSettings.dspTimeを使う設計になっているか確認する

ここで1つでも当てはまったら、次のセクションから読む価値がかなりあります。
音ズレは気合いで合わせるものではなく、仕組みを合わせるものです。




Unityで音がズレる本質的な理由

なぜ音だけズレるのか

「同じタイミングで処理しているはずなのにズレる」
この違和感の正体は、Unityの内部構造にあります。

Unityでは、処理が大きく2つの時間で動いています。

  • ゲーム処理(見た目・ロジック)=フレームベース
  • 音の処理=DSP(オーディオ専用スレッド)

この2つは別々の時計で動いています。

イメージとしてはこんな感じです👇

  • ゲーム側 → 1フレームごとに「カチッ、カチッ」と進む
  • 音側 → 常に一定のリズムで「正確に流れ続ける」

この違いがある状態で「同時に再生しよう」とすると、
どうしてもズレが発生します

つまり、音ズレはバグではなく「構造上の必然」と言えます。

フレーム依存とDSP時間の違い

もう少し具体的に見てみましょう。

項目フレーム時間(Update)DSP時間(音)
精度不安定(FPS依存)非常に高精度
更新タイミングフレームごとサンプル単位
ズレの影響大きいほぼなし

例えば、60FPSの場合は1フレームあたり約16msです。
つまり、Updateで処理する限り、最大16ms単位でしかタイミングを制御できません

一方、音はもっと細かい単位で動いているため、
この差がそのままズレになります。

ここで重要なポイントがあります。

音をフレームで制御してはいけない

これが理解できると、一気に解決に近づきます。

どの程度のズレなら正常か

「少しズレてる気がするけど、これって問題なの?」
この判断ができないと、ずっと調整に迷い続けます。

目安は次の通りです。

  • 〜16ms:ほぼ気づかない(正常範囲)
  • 〜50ms:違和感が出る(要調整)
  • 50ms以上:明確にズレている(修正必須)

特にリズムゲームの場合はシビアで、

  • ±10ms以内 → 理想
  • ±20ms → 許容範囲
  • ±30ms以上 → 違和感あり

という感覚になることが多いです。

ここで覚えておいてほしいのは、
完全にズレゼロは難しいが、違和感ゼロは目指せるということです。

そのためには、「フレームではなくDSP基準で考える」ことが重要になります。




よくある原因5選と解決方法

Updateでタイミングを制御している

症状

  • 再生直後は合っているが、時間が経つほどズレる
  • PCとスマホでズレ方が変わる

原因

Updateはフレーム単位で動くため、FPSが変動するとタイミングもブレます。
その結果、音のような高精度な処理とはズレが積み重なっていきます。

解決方法

  • AudioSettings.dspTimeを基準にする
  • 「経過時間」ではなく「絶対時刻」で管理する

注意点

Time.timeやTime.deltaTimeで音を制御すると、環境差の影響を強く受けます。

再発防止

音関連の処理は「Update禁止」とルール化しておくと安全です。


AudioSource.Play()を使っている

症状

  • 同時に再生したはずの音が微妙にズレる
  • 複数のSEが揃わない

原因

Play()は「その瞬間に再生」ではなく、内部的には次のタイミングで処理されるため、 完全な同時再生になりません。

解決方法

  • PlayScheduled()を使用する
  • 同じdspTimeで再生予約する

注意点

見た目上は同時でも、内部的にはズレていることが多いです。

再発防止

「同期が必要ならPlayScheduled」と覚えておくと迷いません。


BGMと処理を別タイミングで開始している

症状

  • 演出と音が合わない
  • 再生のたびにズレ方が変わる

原因

BGMとゲーム処理の開始タイミングが揃っていないため、 基準がバラバラになっています。

解決方法

  • 同じdspTimeを基準に開始する
  • 「開始時刻」を固定する

注意点

「再生してから合わせる」のではなく、「最初から揃える」ことが重要です。

再発防止

開始処理を1箇所にまとめる設計にするとズレにくくなります。


処理負荷によるフレーム落ち

症状

  • 特定のシーンだけズレる
  • エフェクトや大量処理でズレが発生する

原因

重い処理によってFPSが低下し、Updateのタイミングが乱れています。

解決方法

  • 処理の軽量化(オブジェクト削減・最適化)
  • 負荷の高い処理を分散する

注意点

DSP側は安定しているため、「ズレる=フレーム側の問題」と考えると原因を絞りやすいです。

再発防止

パフォーマンス測定を定期的に行う習慣をつけると安心です。


オーディオ設定(バッファ)の問題

症状

  • 常に一定の遅延がある
  • 操作してから音が鳴るまでワンテンポ遅れる

原因

Audioのバッファサイズが大きいと、その分だけ遅延が発生します。

解決方法

  • Project Settings → Audio → DSP Buffer Sizeを調整
  • 低遅延設定(Best latencyなど)に変更

注意点

バッファを小さくしすぎるとノイズや音切れが発生する場合があります。

再発防止

ターゲット端末ごとに適切な設定を確認しておくと安定します。




正しい音同期の実装方法

音は「未来の時間を予約する」

音ズレを防ぐ一番シンプルで確実な方法は、未来の再生時刻を予約することです。

ここで使うのが AudioSettings.dspTime です。
これは「音の世界の正確な時計」と考えると分かりやすいです。

このdspTimeを使って、「この時刻になったら再生してね」と予約することで、
フレームに左右されない完全な同期ができます。

基本の実装コード

double startTime = AudioSettings.dspTime + 1.0;
audioSource.PlayScheduled(startTime);

このコードでは、1秒後に再生するよう予約しています。

  • dspTime → 現在の正確な音の時刻
  • +1.0 → 少し先の未来を指定
  • PlayScheduled → 指定時刻で再生

ここで大事なのは、「今すぐ再生」ではなく少し未来にすることです。

理由は、準備時間を確保するためです。
ギリギリの時間だと、間に合わずズレる可能性があります。

なぜこの方法でズレなくなるのか

PlayScheduledは、Unityの内部で音声処理(DSP)側に直接スケジュールされます。

つまり、

  • フレームの影響を受けない
  • FPSが落ちてもズレない
  • 環境差が出にくい

という状態になります。

逆に言うと、Play()を使う限り、この精度には到達できません。

BGMと演出を完全に同期させる方法

BGMとゲームの処理を合わせたい場合は、「共通の開始時刻」を使います。

double startTime = AudioSettings.dspTime + 1.0;

// BGM再生
bgmSource.PlayScheduled(startTime);

// ゲーム開始時刻を保存
gameStartTime = startTime;

そして、ゲーム内のタイミングはこう管理します。

double elapsed = AudioSettings.dspTime - gameStartTime;

これで「音と完全に同じ時間軸」で処理できます。

この考え方を使うと、以下のような処理が安定します。

  • リズムゲームの判定
  • 演出のタイミング
  • カットシーンの同期

よくある失敗パターン

実務でよくあるのがこのパターンです。

  • とりあえずPlay()で再生する
  • Updateで位置や演出を調整する
  • ズレたら微調整でごまかす

この方法は一時的には合って見えますが、環境が変わると崩れます。

一度でもズレに悩んだ経験がある場合は、
最初からDSP基準で設計するほうが結果的に楽になります。

一歩進んだ使い方(中級者向け)

より精度を上げたい場合は、以下も検討できます。

  • オフセット(遅延補正)をユーザー設定で調整する
  • 端末ごとにレイテンシを計測する
  • 複数トラックを同時スケジュールする

特に音ゲーでは「完全一致」ではなく、
ズレを前提に補正する設計が重要になります。




すぐ確認できる診断チェックリスト

原因を1つずつ考えるのも大事ですが、実際の開発では「どこから見ればいいか分からない」ことも多いです。
そこで、短時間で原因を絞れるチェックリストを用意しました。

上から順に確認していけば、ほとんどの場合はどこに問題があるか見えてきます。

基本チェック

  • □ 音のタイミングをUpdateで制御していないか
  • □ AudioSource.Play()だけで同期しようとしていないか
  • □ AudioSettings.dspTimeを使っているか
  • □ 同じタイミングで音と処理を開始しているか

挙動チェック

  • □ 時間が経つとズレが大きくなっていないか
  • □ 特定のシーンだけズレていないか
  • □ 実行するたびにズレ方が変わっていないか

環境チェック

  • □ FPSが安定しているか(60fps付近を維持しているか)
  • □ モバイル端末でズレが悪化していないか
  • □ Audio設定(バッファサイズ)が適切か

判断の目安

チェック結果から、原因の方向性を判断できます。

チェック結果考えられる原因
徐々にズレるUpdateなどフレーム依存の問題
毎回ズレが違うPlay()や開始タイミングのズレ
常に一定の遅れオーディオバッファやレイテンシ
特定シーンのみズレる処理負荷(FPS低下)

ここまでチェックして原因の方向が見えたら、前のセクションの対策に当てはめていけばOKです。

音ズレは「なんとなく調整する」と泥沼になりやすいですが、
こうして切り分けていくと、かなりスムーズに解決できます。




よくある誤解と注意点

Play()でも問題ないという思い込み

軽いプロジェクトだと、AudioSource.Play()でもそれっぽく動いてしまうことがあります。

そのため「これで大丈夫」と判断しがちですが、これはたまたまズレが目立っていないだけです。

負荷が上がったり、端末が変わったりすると一気にズレが表面化します。
特に複数の音を同時に扱う場合は、この影響が顕著に出ます。

同期が必要な場面では、最初からPlayScheduledを使うのが安全です。


PCならズレないという誤解

「PCで問題ないから大丈夫」と考えるのもよくあるパターンです。

しかし実際には、音の遅延やズレは以下の要素に影響されます。

  • オーディオデバイス
  • ドライバ
  • CPU負荷
  • OSの違い

つまり、同じPCでも環境が違えば結果も変わります。

モバイル端末ではさらに差が大きくなるため、
「どの環境でもズレにくい設計」にしておくことが重要です。


音ズレは処理落ちだけが原因ではない

「重いからズレている」と考えるのは半分正解ですが、半分は違います。

確かにFPS低下はズレの原因になりますが、
それ以上に大きいのは時間管理のズレです。

例えば、FPSが安定していても、Updateで同期していればズレは発生します。

逆に、DSP基準で実装していれば、多少FPSが落ちてもズレは最小限に抑えられます。


Updateで補正すれば解決できるという考え

ズレた分をUpdateで調整しようとする方法もよく見かけます。

例えば、

  • タイミングを微調整する
  • 遅れを補正するコードを書く

こういった対処は一時的には効果がありますが、
根本の原因が解決されていないため、別のズレが発生します。

特に環境差や負荷変動には対応できません。

補正ではなく「最初からズレない仕組み」を作ることが重要です。


音と見た目は同じ時間で動いているという誤解

これが一番重要なポイントです。

見た目の処理(アニメーションや位置)はフレーム単位、
音はDSP単位で動いています。

つまり、同じ「時間」という言葉でも、実際には別の基準です。

この違いを無視して実装すると、どこかで必ずズレが出ます。

音は音の時間(DSP)で管理する
この考え方に切り替えるだけで、設計が一気に安定します。




実務で使う判断基準と検証方法

音ズレを正しく確認する方法

音ズレは「なんとなく」で判断すると、ほぼ確実にミスります。
人の感覚は意外と曖昧なので、ちゃんとした確認方法を使うのが大事です。

おすすめは次の2つです。

  • メトロノーム音を使う
  • 視覚と音を同時に出す

例えば、

  • 一定間隔で「カチッ」と音を鳴らす
  • 同時に画面でフラッシュやオブジェクト表示をする

この2つを合わせると、ズレがかなり分かりやすくなります。

もし違和感がある場合は、次のように考えます。

  • 常に遅れている → レイテンシ問題
  • だんだんズレる → フレーム依存
  • 毎回違う → 開始タイミングの問題

ズレの体感判断基準

どこまで許容するかの目安も重要です。

ズレ量体感対応
〜16msほぼ気づかない問題なし
〜50ms違和感あり改善推奨
50ms以上明確にズレる修正必須

音ゲーなど精度が重要な場合は、さらに厳しく見ます。

  • ±10ms以内 → 理想
  • ±20ms → 許容範囲
  • ±30ms以上 → 明確にズレ

検証に使う機材

音ズレの確認は、使っている機材でも結果が変わります。

特にBluetoothイヤホンなどは遅延が大きいため、正確な検証には向いていません。

有線のモニターヘッドホンを使うと、ズレの確認がかなりしやすくなります。

オーディオテクニカ ATH-M20xプロフェッショナルモニターヘッドホン
✅ Amazonでチェックする✅ 楽天でチェックする

よくある失敗パターン

実際の開発でよくあるのがこのパターンです。

  • 「なんとなく合っている」でOKにする
  • 環境ごとの違いを確認しない
  • 最後にまとめて調整しようとする

このやり方だと、後半で必ず破綻します。

特に音ズレは、後から直そうとするとかなり大変です。

最初の段階で検証しながら作ることが、結果的に一番ラクです。

実務でのおすすめ運用

  • 開発初期からDSP基準で設計する
  • ズレ確認用のテストシーンを用意する
  • 複数環境(PC・スマホ)で確認する

ここまでできていれば、音ズレで詰まることはほぼなくなります。




時間管理の理解を深める

音ズレを根本から理解するためには、「Unityの時間の仕組み」を押さえておくことが重要です。

特に混同されやすいのが次の3つです。

  • Update
  • FixedUpdate
  • DSP時間(AudioSettings.dspTime)

それぞれ役割が違うので、ここを整理しておきましょう。

UpdateとFixedUpdateの違い

Unityには2つの代表的な更新処理があります。

処理特徴用途
Update毎フレーム実行(不安定)入力・表示
FixedUpdate一定間隔で実行(安定)物理演算

ここで注意したいのは、どちらも音の時間ではないという点です。

つまり、

  • Update → フレーム依存
  • FixedUpdate → 物理用の時間

なので、音の同期にはどちらも適していません。

このあたりの理解が曖昧だと、「どっちでやればいいの?」と迷いやすいです。

より詳しく知りたい場合はこちらも参考になります👇

Time系とDSP時間の違い

もう一つ混同されやすいのが、Time系の値です。

時間特徴用途
Time.timeゲーム開始からの時間一般的な処理
Time.deltaTime前フレームとの差分移動・補間
AudioSettings.dspTime音専用の高精度時間音同期

ここでのポイントはシンプルです。

音はdspTime、それ以外はTime系

このルールを守るだけで、設計がかなり整理されます。

なぜ時間を分けて考える必要があるのか

Unityは効率よく動かすために、処理を分けています。

  • 画面表示 → フレーム単位でOK
  • 物理 → 一定間隔でOK
  • 音 → 高精度で処理する必要あり

この違いを無視して全部同じ時間で扱うと、ズレや不具合が出ます。

逆に言うと、用途ごとに時間を使い分けることで、

  • 安定した挙動になる
  • 環境差に強くなる
  • 調整がシンプルになる

というメリットがあります。

実務でのシンプルな判断ルール

迷ったときは、次のルールで判断できます。

  • 見た目の動き → Update
  • 物理挙動 → FixedUpdate
  • 音のタイミング → dspTime

この3つを切り分けるだけで、設計のミスはかなり減ります。

特に音ズレに関しては、このルールを守るかどうかで結果が大きく変わります。




まとめ

音ズレの原因は一見バラバラに見えますが、本質はとてもシンプルです。

「音の時間」と「フレームの時間」を混ぜていること
これがほとんどの原因です。

重要なポイントをもう一度整理します。

  • 音はDSP(AudioSettings.dspTime)で動いている
  • UpdateやTime系で同期するとズレる
  • PlayScheduledを使うと高精度で同期できる

まず最優先で確認するべきポイントはこの3つです。

  1. AudioSource.Play()を使っていないか
  2. Updateベースで同期していないか
  3. dspTimeを使っているか

ここが整理できていれば、音ズレの大半は解決できます。

また、実務では次の考え方がとても重要です。

  • 音は「未来の時間を予約する」
  • ズレは後から補正するのではなく、最初から防ぐ
  • 環境差がある前提で設計する

私自身も最初は「なんとなく合わせる」方法で進めてしまい、
後から全部作り直すことになったことがあります。

でも、DSP基準で設計するようにしてからは、
音ズレで悩むことはほぼなくなりました。

少し考え方を変えるだけで、安定性が一気に上がります。

音ズレは厄介に見えて、実は「仕組みで解決できる問題」です。
今回のポイントを押さえて、安定したオーディオ制御を作っていきましょう。


よくある質問(FAQ)

Q
AudioSource.PlayDelayedは使えますか?
A

使うこと自体は可能ですが、厳密な同期が必要な場合には注意が必要です。

PlayDelayedは「指定した時間だけ遅らせて再生する」便利な機能ですが、内部的にはフレームの影響を受けるため、 サンプル単位の精度は保証されません

そのため、

  • SEの簡単な遅延再生 → OK
  • リズムゲームや同期演出 → 不向き

と考えると分かりやすいです。

精度が必要な場合は、PlayScheduledを使うのが安全です。

Q
モバイルでも同じ対策でいいですか?
A

基本的な対策は同じですが、モバイルは特に遅延が出やすい環境です。

主な理由はこちらです。

  • オーディオバッファが大きめに設定されている
  • デバイスごとに性能差が大きい
  • バックグラウンド処理の影響を受けやすい

そのため、次のような追加対策も検討すると安定します。

  • DSP Buffer Sizeを調整する
  • オフセット調整(ユーザー設定)を用意する
  • 複数端末で検証する

特に音ゲーなどでは「端末ごとに微調整できる仕組み」が重要になります。

Q
完全に音ズレをゼロにできますか?
A

理論的には「完全なゼロ」は難しいですが、体感上ズレを感じないレベルにはできます。

理由は、環境によって次のような違いがあるためです。

  • オーディオデバイスの遅延
  • OSやドライバの違い
  • ハードウェア性能差

ただし、DSP時間を基準にした実装を行えば、

  • ズレを最小限に抑える
  • 安定した同期を維持する

ことは十分可能です。

実務的には、

  • DSP基準で設計する
  • 必要に応じてオフセット補正を入れる

この2つを押さえておけば問題なく運用できます。

※当サイトはアフィリエイト広告を利用しています。リンクを経由して商品を購入された場合、当サイトに報酬が発生することがあります。

※本記事に記載しているAmazon商品情報(価格、在庫状況、割引、配送条件など)は、執筆時点のAmazon.co.jp上の情報に基づいています。
最新の価格・在庫・配送条件などの詳細は、Amazonの商品ページをご確認ください。

スポンサーリンク