Cinemachine は 3D オーディオを考慮していないようで、カメラが切り替わる時に意図しない風切り音がなってしまう。という問題。
Cinemachine は3Dオーディオを考慮していないようで、カメラが切り替わる時に意図しない風切り音がなってしまう。という問題。#unity3d pic.twitter.com/ZioPKIqPQu
— サトー (@sator_imaging) September 2, 2021
もくじ
問題の原因
Cinemachine は設定に従ってメインカメラを瞬間移動/高速移動させる、という機能。
結果としてカメラにくっついている Audio Listener も高速移動することになる、というのが風切り音が鳴ってしまう問題の原因。(正しいと言えば正しい結果)
※ Cinemachine によってメインカメラが瞬間移動している様子
最初に示した動画は Blend を0.1秒に設定しているのでまだ聞くに堪えるが、↓ のように Blend 方法が Cut の場合、瞬間移動による破裂音が鳴る。完全にエラー。
3Dオーディオはカメラ本体が動かないと変化が生まれないから、ズームで画角が変わった時にも音量が変わるようにした
— サトー (@sator_imaging) August 27, 2021
そしたらズームしたときに破裂音が出るように、、、消し方が分からん
OnAudioFilterRead で音鳴らしてるせいかなーー?#realtimevfx #generativeArt #madewithunity pic.twitter.com/csnZB0zbqi
風切り音は 3D オーディオ設定の Doppler Level をゼロにすると消すことが出来るが、鳴って欲しい風切り音も消えてしまうし、そもそもそういう問題じゃない。
対処方法
Audio Listener の瞬間移動/高速移動が原因なので、メインカメラからオーディオリスナーを剥がしてやれば解決できる。
CinemachineVirtualCamera
Cinemachine を使う際には Main Camera についている Audio Listener は削除し、Cinemachine Virtual Camera すべてに Audio Listener をアタッチして高速移動が起きないようにする。
手動でも構わないが、面倒なのでスクリプトで生成すると良い。
void OnEnable()
{
// add audio listener to virtual camera.
foreach (var vc in FindObjectsOfType<CinemachineVirtualCamera>())
{
var al = vc.GetComponentInChildren<AudioListener>();
if (al) continue;
al = vc.gameObject.AddComponent<AudioListener>();
al.enabled = false;
}
}
※ Start()
は後述の Activated イベントより後に実行されるので OnEnable()
で行うこと。
CinemachineBrain
リスナーを追加しただけだとダメで、CinemachineBrain
の Camera Activated イベントでリスナーの有効・無効を切り替える必要がある。
public void OnCinemachineCut(ICinemachineCamera nextcut, ICinemachineCamera prevcut)
{
// sometimes CinemachineBrain is passed, why?
if (nextcut.GetType() != typeof(CinemachineVirtualCamera)) return;
// disable first.
if (null != prevcut)
{
foreach (var al in prevcut.VirtualCameraGameObject.GetComponentsInChildren<AudioListener>())
{
al.enabled = false;
}
}
var listener = nextcut.VirtualCameraGameObject.GetComponentInChildren<AudioListener>();
if (listener) listener.enabled = true;
}
おわりに
破裂音の原因なんなんだと探ったら、すげー単純な問題。気付けばなんてことないが、バグといっても差し支えない感じ。
メインカメラを移動させる手法はパラメーター管理が楽でいいけど、時間軸に依存したエフェクト(モーションブラーや3Dオーディオ)なんかに悪影響があるんで、Cinemachine には標準でそれらに対処する機能を追加してほしいところ。
以上です。お疲れ様でした。