
こんにちは。トイロジックでプログラマーをしている、うしと申します。本記事では、Wwiseを使った3Dゲームにおけるサウンドの遮蔽感の計算について、実装・検討中のアイデアをご紹介します。
目次
サウンドの遮蔽って?
音の距離減衰はみなさんよくご存じだと思います。音は、そのエネルギーが拡散することにより、音源からの距離が離れるにしたがって、音量が小さくなっていくことが知られています。
ゲームにおける距離減衰は、たいていのサウンドミドルウェア、ゲームエンジンにおいても当然のように標準実装されており、ほとんどの場合簡単に設定することができます。世に出ているほとんどすべての3Dゲームでその効果を体感できるはずです。
ゲーム開発の経験がある方は見たことがあると思いますが、多くの場合、横軸が<音源からの距離>
、縦軸が<音量>
のカーブ(グラフ)として設定します。
もちろん演出のため、一定距離内は減衰しないようにする、など様々な形状のカーブをゲームでは設定します。
ところで、現実の音の減衰って距離によるものだけでしょうか?隣室の住人のテレビの音、窓の外から聞こえる車や電車の音、パーテーション越しに聞こえる同僚の声….
間に障害物があったとき、音は小さく、くぐもって聞こえてきます。これは音の透過や回折といった現象によって生まれる効果です。
これら、障害物の遮蔽によって音に生じる効果の事を、今回はサウンドの遮蔽と呼んでいます。
今回はこのサウンドの遮蔽をゲーム上で表現するために、どういったことをどのように計算するのかというアイデアをWwiseを使った例でご紹介いたします。
※WwiseのSpatialAudioは使わないものとして進めていきます。
Wwiseの遮蔽パラメータ – ObstructionとOcclusion
Wwiseでサウンドの遮蔽を扱うにあたって、Wwise上のObstruction
とOcclusion
というパラメータについて簡単に説明します。
詳しくは、こちら
Obstruction
とOcclusion
は、ゲームオブジェクトが個別に持つbuilt-inパラメータの一種です。いわゆる”Distance”(リスナーとエミッターの距離)のように、Wwise上に初めから定義されているパラメータの仲間ということです。
ただし、Distanceなどと違ってWwise側で自動計算されるのではなく、SetObjectObstructionAndOcclusionというAPI(関数)を使って、RTPC的に0.0 ~ 1.0の値をゲーム側から設定してあげる必要があります。
Obstruction
サウンドが部分的に遮蔽されることをシミュレートするパラメータで、Wwise上では直接音に影響を及ぼします。

Occlusion
サウンドが完全に遮蔽されることをシミュレートするパラメータで、Wwise上では音全体(直接音と間接音:AUX Send)に影響を及ぼします。

ちなみに、直接音とは、音源から発生した音が周囲の物体に反射せず直接リスナーに伝わった音のことで、間接音とは、天井や壁に反射してリスナーに入る音のことを指しています。
直接音の音量(Dry)は、OutputBusVolumeとして、間接音の音量(Wet)は、部屋の残響(リバーブ)として表現するため、リバーブ用AUXバスへのSend量(AuxiliarySendVolume)としてWwise上では表現されます。
Wwise(オーサリングツール)上では、Project > Project SettingsのObstruction/Occlusion
のタブから、各パラメータに対する音量・LPF・HPFの影響がグローバルに設定可能になっています。


ちなみにWwise2022以降は、上記グローバル設定に加え、各Attenuation Curve (ShareSets) から個別のオブジェクトの影響量を調整可能になっています。
Obstructionの計算
Obstructionは直接音の遮蔽量、ということでした。これを今回は、音源とリスナー間の直線がどの程度遮蔽されているか?というパラメータを出すことを考えます。
直線といっても、音源とリスナーを結ぶ直線レイを1本飛ばして当たったかどうか…では、0.0 ~ 1.0の値にするのは難しそう…といったあたりを念頭に置いて考えます。
案1:1本のレイキャストで、当たった物体の大きさと当たった位置から遮蔽量を計算する。
これはガンホー・オンライン・エンターテイメント様の「UE4×Wwise×Nintendo Switch――『ニンジャラ』サウンド制作事例」にて、”ワンレイ遮蔽”として紹介されていた方法で、リスナーと音源間で0.2秒ごとに1本レイを飛ばし、「当たった物体の中心からどのくらい離れているか」を遮蔽量として使ったというものでした。
案2:リスナーの周りから音源にむかって複数本のレイを飛ばす
これはレイが1本だと0か1かの値にしかならないので、複数本飛ばしてその統計をとることで0.0 ~ 1.0の値を取得しよう、というアイデアになります。複数本飛ばす発想なので、処理負荷を考えて、必ず本数や発射・更新間隔などを細かく調整できるようにする必要があります。
実際に実装してみた例を紹介します。
- リスナー位置と、その左右50cmの位置から、エミッターに向かって1本づつレイキャストする
- 中、右、左、中、右、左、….みたいな感じ
- 間隔は1本ごとに0.2秒
- 1本の衝突情報は0.66秒保持
- 賞味3~4本分のデータを常に持っている感じ
- 保持されている衝突情報のうち、衝突した情報の割合をObstructionとする
Obstructionの計算
Occlusionは間接音も含めた音全体の遮蔽量、ということでした。これを今回は、音源とリスナー間の空間がどの程度音が伝わりやすいか?というパラメータを出すこととして考えます。リスナーと音源間を隔てる壁の関係を考えてみます。
案1:空間を隔てる壁の面積のうち、穴の開いていない面積の割合をつかう
穴がいっぱい開いていれば音は通りやすいはずだし、無ければ音はほとんど通らないはず。という発想です。ダンジョン生成システムなどで、部屋の壁と穴の大きさの情報を持っていれば、レイを飛ばさずとも計算ができることが大きな利点になります。

ただし、これは同じ壁を挟んでいる間は、リスナーと音源の位置が変わっても変更されない値になることに注意が必要です。音源またはリスナー、あるいはその両方ともが、穴の前にいるにもかかわらず、遮蔽感が全く変わらない..ということがありえます。(その部分は別途レイを飛ばしたり、Obstructionの値で補う…というアイデアもアリだと思います。)
案2:壁の厚みを考える(厚み遮蔽)
これは壁が厚ければ音は透過しにくいはず。という発想です。これであれば、リスナー・音源のリアルタイム位置による値更新が期待されます。ただし、レイを飛ばす必要があります。
実際の実装例としては、
- リスナーから音源に向けて、レイを1本飛ばし、衝突位置を記録
- 反対からでもOK
- Obstruction計算でレイを飛ばしたりしていれば、それを利用するのもあり(1本レイを削減できる)
- レイが衝突しなければ、0.0で終了。衝突していれば、反対側からもレイを飛ばし衝突位置を記録.(今回であれば音源 → リスナー)
- 1.と2.の衝突位置の距離(厚み)を測り、これの”基準の厚さ”に対する割合を値とする
- 仮に基準が200cmで厚みが100cmなら0.5。厚みが200cm以上なら1.0


注意事項として、上図の赤丸部のように、移動などして間に別の障害物が挟まったときに急に大きな値が算出されることがあります。コリジョンチャンネルなどで壁だけを対象にするなどの工夫も可能ですが、障害物コリジョンも遮蔽計算の対象にしたい場合、「見えない隣の部屋で突然遮蔽が強くなる」ことで、違和感を覚える場面もあるようでした。
案2.5:厚みの代わりにリスナーと音源間の距離をつかう
間に障害物が入ってしまう…という欠点を回避するために、厚みの代わりに、(一定距離を基準に)リスナーと音源間の距離に対する割合をつかう,という方法も実装してみました。
これは遮蔽物があるとき限定の、実質追加の距離減衰になってしまうのですが、直感的な調整ができて、聴いたときの違和感も少ないということでした。
おそらく、以下のようなことが遮蔽の影響間としてシミュレートされていそうです。
- 音源が壁に近ければ、音のエネルギーが大きい(距離減衰があまりされていない)状態で壁に吸われるので、十分に吸収されないで、音がいっぱい透過する。
- リスナーが壁に近ければ、壁を透過した音の距離減衰が弱いうちにリスナーに到達するので、音が大きい

最後に
いかがだったでしょうか?
ところでゲームにおいて、サウンドの遮蔽は必ずしも扱われるわけではありません。距離減衰や部屋の反響感(リバーブ)くらいの実装はあっても遮蔽までは採用されないことはよくあります。
その理由は以下のようなことが考えられます。
1.実装に工夫と理解が必要 & どうしても処理負荷がかかる
ご紹介してきたように、遮蔽を計算するには、音源ごとにレイキャストしたり、部屋情報を検索したり、といった軽くないであろう処理をリアルタイムに行う必要があります。
1フレームのレイの最大数、レイの時間間隔、飛ばし方、値の更新間隔、リスナーから遠くの音源を間引くなど…それぞれ処理と表現のバランスをとれるように調整できる必要があります。
2.ユーザーさんにとって不利益になることがある
たとえば、オンライン対戦ゲームにおいて、足音・射撃音で他プレイヤーの位置を把握したいのに、壁を挟んでいると音が小さくて位置把握が難しい…など。
それがリアルで正確であったとしても、ゲームの体験として最適とは限らないということです。
上記を踏まえ、使いどころを正しく理解し、提案・実装することが大切です。
最後になりますが、これまでご紹介しましたのは様々な実装を試してきたなかでのアイデアのいくつかというものであり、サウンド遮蔽はこれをやれば完璧!というものではないことにご注意ください。
みなさまがサウンドの遮蔽感のことを考えるきっかけになったり、実装してみるときの何かヒントになれば幸いです。