takeyohのおぼえがき

気になったこと、試したことの記録です。

別のbankファイルにある音源をextensionで制御する。(AI車両として使うときの注意点も)

car mod作成してると、extension/ext_config.iniにscriptを追加して、音や動画なんかを動的に制御することがあります。
今回のサンプルは救急車ですが、エンジン音とは別にサイレン用のbankファイルを作り、それを鳴らしてみたのでその覚書です。

まず救急車のサイレン用音源を用意します。(今回はフリーの音源を使用)
それをfmodにインポートして、bankファイルを作ります。
(ここら辺の作り方は全部書くとメンドイので省略)
注意点として、サイレン音源を入れたトラックのマスターボリューム部分あるDopplerというスイッチをONにしておきます。

これをしておくと、ゲーム内で再生したとき、近づいたり、遠のいたりするときのあの独特な音の変化(ドップラー効果って言いますね)が再現されます。
救急車のサイレンは、これが無いと雰囲気出ないですからね!

そして今回作ったのがamblulance.bank(あ、スペル間違ってる、けどいいや)と、下記のGUIDs.txtです。

{8ff99e75-e3da-4f4a-97b3-854c1492342f} event:/ambulance/silen
{af471175-1aab-4641-84fa-c33bcd9fc869} event:/ambulance/silen2
{06a8df0d-23d4-4b55-9ab8-eaad7dc2d19b} bank:/amblulance

(car modフォルダ)/extensionにsfxフォルダを作成して、この2つのファイルをコピーします。
(extension直下でも可能だと思いますが、一応慣習に合わせて・・・)

可視性重視で、今回音を制御するlua scriptを外だし(sound.lua)にします。
sound.luaの中身はこんな感じ。

ac.loadSoundbank("./sfx/amblulance.bank", "./sfx/GUIDs.txt")
local sirenSound = ac.AudioEvent("event:/ambulance/silen", true)
local sirenSound2 = ac.AudioEvent("event:/ambulance/silen2", true)

function script.update(dt)
    sirenSound:resumeIf(car.extraA or car.isAIControlled)
    sirenSound2:resumeIf(car.extraB)

--make sure sound is following the car
sirenSound:setPosition(vec3(0, 0.68, 0.0))
sirenSound2:setPosition(vec3(0, 0.68, 0.0))
end

最初の3行で、追加のbankファイル読み込みと音を鳴らすイベントを割り当てます。
ちなみにここのsilenが「ピーポー」の音、silen2が「う~~~~」の音です。
script.update内が制御部分になりますが、難しいことはしていません。
XXX:resumeIfはかっこ内の条件がtrueになると音がなり、flaseになると音が止まるという処理です。
car.extraAはextraAキーがオンの時、 car.isAIControlledはこの車がAI車両として動いている場合にtrueになります。
silen2はextraBに割り当てました。
XXX:setPositionは音の出る場所ですね。車の原点(0,0,0)からの相対座標になってます。

そして、ext_config.iniに次を追記します。

[SCRIPT_...]
SCRIPT = "sound.lua"
ACTIVE_FOR_NEAREST=12 ;THIS script will execute for the nearest X instances of this vehicle
ACTIVE_FOR_UNFOCUSED=1

設定出来たら、救急車を自車に設定してゲームを起動。extraA、extraBで音が出ることを確認し、リプレイなどでドップラー効果が表現されていればOKです。


ここからはAI車両として使う場合の補足事項です。
通常car modのext_config.iniに追記したlua scriptはその車両の視点に移動しないと動作しないようです。
上記でいうと、ACTIVE_FOR_NEAREST=1の状態。

”ACTIVE_FOR_NEAREST=12”は、自車とこの車(救急車)の間の車の数が12台以下になると動作するという設定だそうです。
小さすぎると、救急車にかなり接近しないと音が鳴らないですし、大きすぎるとサイレンを鳴らす処理が動き続けることになるので、少なからずゲームに負荷がかかると思います。

これによって、AI車でもlua scriptを実行させることはできるのですが、注意点が2つあります。
1)lodAの車両のみ動作します。
この救急車もlodA~lodDを用意しており、車両に近づくにつれ、lodD->C->B->Aと切り替わって表示されます。
そして、lodBからlodAに変わった瞬間から上記のsound.luaが実行されます。
そのため、ACTIVE_FOR_NEARESTに大きな数字を入れても、近づいてlodAに切り替わらないと音が鳴らないということになります。
この解決策としては、data/lods.iniでlodAのkn5のみを利用する(lodB~lodDを使わない)ようにすれば可能です。
が、その車は常にlodAで表示されることになるので、ゲーム負荷が高くなります。

2)assettoserverでは動作しない。
上記の設定は、スタンドアロンのTrafficレイアウトであれば機能しますが、assettoserverのAI車両として利用すると機能しません。
おそらく、assettoserver実行上では、AI車両のscriptはすべて機能しない(というか無視されている)のではないかと思います。
こちらはassettoserverの仕様だと思いますので、しょうがないですね。


ということで、実は私が作成した救急車modのサイレンはこの方法は使っていません。(笑)
fmodを使って、車のbankファイルにおいてexterior engine soundにピーポーの音を、ホーンにウ~の音を埋め込んであります。
これだとAIでの動作はどんな場合でも期待通りの動きをしますが、extraキーでオンオフを制御したり、車の音を別のbankファイルに入れ替えたりとかができなくなります。

作成するcar mod を自車走行用メインで、音を追加したいという場合はこの記事の方法が良いと思います。
AI車走行用メインだったら、最後に書いたfmod自体を作りこむ方が良いと思います。

/* -----codeの行番号----- */