takeyohのおぼえがき

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

FBX_MATERIALエラーの対処方法

ターンパイクの2Dの木をたくさん生やす作業をしています。
やり方は書くのが面倒なのでこちらを参照!
modelinghappy.com

で、大量に増やした木をオブジェクトに変換してFBXでエクスポートし、ksEditorにインポートすると、マテリアルの中に見慣れないFBX_MATERIALというのがたくさん出てきました。

これ、もともとblenderで作成しているときには、存在しないマテリアルなのですが、ksEditorで読み込んだオブジェクトの一部にこれが割り当てられている状態になっています。
もともとこのエラーはオブジェクトの面に適切なマテリアルが設定されていない部分がある場合に出力されるもののようですが、今回の木のオブジェクトは、すべてマテリアルが設定されているので塗り残しは無いはず。木の数(今回の例では1000本)が多いので、エクスポートする際に、何かバグってるんかな?と思って困っていました。
ググってみたところ、解決策が書かれていたので、覚書しておきます。

1.エクスポートする対象のオブジェクトをすべて選択。
2.オブジェクト>関係>シングルユーザー化>オブジェクトとデータ を選択。

3.あとは、いつも通りFBXでエクスポートしてksEditorで読み込む。

すると、先ほどのFBX_MATERIALというマテリアルが出なくなりました!

この処理が何を意味するのか分かっていませんが、とりあえず記録しておきます!

CPHYS_SCRIPTの使い方&注意事項

CSPの機能の一つに、物理制御しているscript.luaから光やアニメーションを制御するextension側にパラメータを受け渡すことができます。
公式WIKIはこちら。
github.com

これの、
CPHYS_SCRIPT_0: value #0 set by custom physics Lua script;
CPHYS_SCRIPT_1: value #1 set by custom physics Lua script;
CPHYS_SCRIPT_2: value #2 set by custom physics Lua script;
CPHYS_SCRIPT_3: value #3 set by custom physics Lua script;
CPHYS_SCRIPT_4: value #4 set by custom physics Lua script;
CPHYS_SCRIPT_5: value #5 set by custom physics Lua script;
CPHYS_SCRIPT_6: value #6 set by custom physics Lua script;
CPHYS_SCRIPT_7: value #7 set by custom physics Lua script;

この8つがそれです。(8個まで個別に制御できるってことですね。)

よくあるAnimationやEmissiveで使われる
INPUT=〇〇
の〇〇に入れることになります。
例えば、

[EMISSIVE_...]
INPUT = CPHYS_SCRIPT_0
INPUT_THRESHOLD = 5000
NAME = alertLight
COLOR = 255, 0, 0

とか書いておくと、
CPHYS_SCRIPT_0の値が5000を超えると、alertLightというオブジェクトが赤く光る
ということになりますね。

で、CPHYS_SCRIPT_0の値はどうやって制御するのかというと、車の制御側になる、data/script.luaフォルダ内で定義します。
CPHUS_SCRIPT_0の値は、ac.accessCarPhysics().controllerInputs[0] で制御します。
0から7まであるので、ac.accessCarPhysics().controllerInputsも[0]から[7]まであり、一対一で対応しています。
例えば、data/script.luaの中に

ac.accessCarPhysics().controllerInputs[0] = ac.getCar().rpm

とか書いておくと、CPHYS_SCRIPT_0には随時現在のエンジン回転数(RPM)が入力されるようになります。
(実際にはINPUT=RPMというのがあるので、こんな面倒なことはしないですけどね。)

こうして、script.luaでいろいろな制御をして、その結果をアニメーションや光に反映させたいときは、CPHYS_SCRIPTを使って制御することが出来るようになります。
が、一つ欠点が。
これ、ゲームプレイ中はちゃんと機能するのですが、リプレイでは機能しません。リプレイ中script.lua自体は機能するのですが、CPHYS_SCRIPT側がデータを受け取って処理することが出来ません。
なので、車の外から見てわかるアニメーションや光などはリプレイで動作しないことに。すごく違和感が出てしまうので、そのような場合はあきらめて割り切るか、違う方法で制御することを考えましょう。

エンジンのパワーを選択

通常car mod のエンジンのパワーはdataフォルダのpower.lutでRPMごとに定義されています。
今回は、ノーマルタイプのBRZを作り始めたのですが、Xで馬力を選べるようにするのはどうか?というコメントを頂いたので、実装してみました。その覚書です。

注)car.iniのHEADERセクションでは
VERSION=extended-2
に設定する必要があるようです。(ほかのVERSIONでも動くのか、すべては試せてません)

まず、選べる馬力の種類を決めます。
今回は他の車のデータを参考にいかの4つにしました。

FD(1200PS) → フォーミュラードリフトクラス
ProAm(600PS) → プロアマクラ
Street(200PS)  → ストリートクラス(ノーマル)
Grassroot(150PS)→ 少しパワー弱め

まずこの馬力の選択肢を定義するファイルを作ります。
dataフォルダ内に、engine_map_setup.lutというファイルを作ります。(拡張子注意)
中身はこれです。

FD(1200PS)  | 0
ProAm(600PS)| 1
Street(200PS) | 2
Grassroot(150PS)| 3

続いて、それぞれの馬力の設定ファイルを作ります。
FD(1200PS)は通常の6倍のパワーになるので、dataフォルダ内にengine_map0.lutというファイル名で、以下の様に書きます。

0|6.00
10000|6.00

今回のBRZはノーマルレベルで作成しているので、車の性能としては200PSです。1200PSにするために6倍にしています。
0と1000RPMしか設定してませんが、その途中も細かく制御したいときは、追加していけばよいと思います。
さらにdataフォルダ内にengine_map1.lutというファイル

0|3.00
10000|3.00

engine_map2.lutというファイル

0|1.00
10000|1.00

engine_map3.lutというファイル

0|0.75
10000|0.75

を作成しました。それぞれ600PSなので3倍、200PSなので1倍、150PSなので0.75倍しています。

それができたら、次はエンジンの設定を追加します。dataフォルダのengine.iniに以下を追加します。

[MAP]
DEFAULT = 2 ; default map index
MAP_0 = engine_map0.lut 
MAP_1 = engine_map1.lut 
MAP_2 = engine_map2.lut 
MAP_3 = engine_map3.lut 

今回はStreet(標準)をデフォルトにしたいので、DEAFULTは2にしています。

さらに、ゲームスタート後、PITの設定画面で、これを選択させることもできます。
dataフォルダのsetup.iniに以下を追記します。

/////////////////////////////////////////////////////
;Drift Class
/////////////////////////////////////////////////////

[ENGINE_MAPS]
SHOW_CLICKS = 0
TAB = DRIFT CLASS
NAME = Select Class
LUT = engine_map_setup.lut
POS_X = 0.5
POS_Y = -0.750
HELP=Engine Map

これを追加すると、PITを選んだとき、上のメニューの中に「Drift Class」というタブが出てきます。
それを選ぶと、クラスが選択できるようになります。クラスの設定は最初に作成したengine_map_setup.lutを参照しています。

以上になります。
あとは、お好みでパワーを増やすなり、減らすなり、いろいろ試してみましょう~。

個人設定がonedriveのdocumentフォルダにあるとゲームに不具合が出る件

今回は、mod技術の話ではなく、動作環境についての覚書です。

先日、CSP0.1.80 preview428が出たとき、適用するとオフラインでのゲームはできるのですが、オンラインサーバに入ろうとするとエラーが出て止まってしまう問題がありました。
ログを確認すると、(非常にわかりにくいですが)、INIファイル読み込み時にonedriveのパスにあるファイルを読みに行こうとしていてクラッシュしているような気が…。
(あくまで予測でして、明確にログにそう書かれていたわけではありません。)

再インストールなども試しましたが解決できなかったので、この予測を検証することにしました。
結論としては、「設定ファイルはonedriveフォルダに格納してはいけない」です。
(CSP0.1.80 preview428からNGです。それ以前のバージョンはonedriveフォルダでも動きます。)

ここから先はwindowsのバージョンなどによっても設定の仕方や画面UIが異なるので、ググって調べてください。
windowsの設定変更に関わる内容ですので、保証はできません。ご自身の責任においてお試しください。

やるべきことは、
①one driveアプリでログイン
②バックアップの管理画面でドキュメント(document)フォルダのチェックを外す(バックアップ対象から除外する)
③ドキュメントフォルダのアイコンを右クリックして、「場所」タブを選択。
④「標準に戻す」を押す。(C:\User\ユーザ名\Documentsというフォルダになると思います)
⑤「OK」を押す。
⑥One drivenのdocumentフォルダに保存されているフォルダ・ファイルを④のフォルダにコピーor移動する。
 (OnedriveのdocumentフォルダはC:\User\ユーザ名\OneDrive\ドキュメントにあります。)

通常ドキュメントフォルダの下には「Assetto Corsa」というフォルダがあるはずです。このフォルダが
「C:\User\ユーザ名\OneDrive\ドキュメント」ではなく「C:\User\ユーザ名\Documents」の下にあればOKです。

私は今回初めてですが、ゲームのアプリではよくあることのようですね。
こちらのフォルダ設定変更およびフォルダ・ファイルの移行により、CSP0.1.80 preview428でもオンラインサーバに入れるようになりました。

ちなみに、Assetto Corsa Evoluzioneでも同じことが原因でレースがスタートできないなどの不具合が発生します。
ご参考になれば幸いです。

テクスチャをカスタマイズする(track編)

SRPのカスタマイズネタを動画でアップしてたら、SRPの道路のスキンを変えたいからやり方教えてというリクエストがあったので、書きます。
If you cannot read Japanese, please use a translation tool.


今回はSRP(0.9.1でも0.9.2PTBでもどちらでもよいです)を例に進めますが、他のtrackでもやりかたは同じです。
まずカスタマイズしたいテクスチャの情報を取得します。

ゲームを起動し、カスタマイズしたいテクスチャがあるところまで移動します。
右のメニューからObjects Inspectorを起動します。

Objects Inspectorのウインドウが表示されたら、altキーを押しながら、カスタマイズしたいテクスチャ(今回は路面)を左クリックします。
すると、Objects Inspectorには選択したメッシュ(物)とマテリアル(素材)の情報が表示されます。

今回選択した道路は、メッシュ名がgeo_road_01.006、マテリアル名がmat_road_01ですね。
で、このマテリアルには4種類のテクスチャが設定されています。
上記の例ですと、Objects InspectorのtexturesタブでtxDiffuse、txNormal、txMaps、txDetailの4つが設定されています。
この中で色や見た目に影響するのが、txDiffuseです。
Textureの列にマウスカーソルを合わせると、ファイル名が確認できます。
クリックすればファイル名がコピーされます。

このテクスチャのファイル名は”AREA_ZZ_01.GTF_tex_159.dds”ですね。

この行の一番右に薄く見えている四角にチェックを付けると、設定されているテクスチャを確認することが出来ます。

サイズは1024x1024のサイズであることがわかります。

ここまでわかったら、カスタマイズした差し替え用の画像ファイルを、同じ名前・サイズで作成します。
今回はddsフォーマットに対応したツールが必要です。(私はpaint.netを使っています。)
今回はサンプルとして、真っ白の画像を用意してみました。

ファイル名はAREA_ZZ_01.GTF_tex_159.dds、サイズは1024x1024です。
そしてこれを保存します。
前にも書きましたが、assettocorsaで使用するddsファイルは、”BC3(線形,DXT5)"じゃないと認識できません。


ファイル保存できましたか?
次に、このファイルをコピーしていきます。
今回の例はSRPの0.9.1にします。
(assettocorsaインストールフォルダ)/countent/tracks/shuto_revival_project_beta/skins
に移動します。skinsフォルダが無い場合は、作成します。
ここにcm_skinsというフォルダを作成します。そしてそのフォルダの中に自作して適用したいテクスチャファイルを格納するフォルダを用意します。
ここではtky_snowという名前にしました。
そうするとパスはこうなるはずです。
(assettocorsaインストールフォルダ)/countent/tracks/shuto_revival_project_beta/skins/cm_skins/tky_snow →(1)
この(1)のフォルダに先ほど作成したAREA_ZZ_01.GTF_tex_159.ddsをコピーします。
あと、ui_track_skin.jsonというファイルを作成します。(テキストファイルです。拡張子がtxtじゃないので注意)

{
  "name": "Snow(takeyoh Custom)",
  "track": "shuto revival project",
  "id": "snow",
  "tags": [
    "season"
  ],
  "country": "",
  "description": null,
  "author": "takeyoh",
  "version": null,
  "url": null,
  "categories": [
    "season"
  ],
  "priority": 0.0
}

いろいろパラメータがありますが、ここでは割愛。name:のところに書いた文字列はこのスキンの名前になります。


続いて、content managerを起動。driveのsingleを選択します。
trackでSRP0.9.1を選択します。
すると、下にこういうメニューが表示されると思います。

先ほどjsonのname:で指定した名前が表示されています。
ちなみに左のアイコンが壊れているのは、(1)のフォルダにアイコン用の画像ファイルが無いからです。
(1)のフォルダにpreview.pngというpngフォーマットの画像ファイルを置くと、ここに表示されるようになります。

で、この名前の左にあるチェックボックスにチェックを付けると、自分で作ったテクスチャがゲームに反映されるようになります。
反映を止めたい場合は、このチェックボックスのチェックを外せばOKです。

チェックを付けた状態でゲームを始めると、道路が白くなっていると思います。
また、先ほどのテクスチャファイル調査のところにあった、txNormalは凹凸を表現するものです。ノーマルマップと呼ばれます。
これの詳細、作り方はググってみてください。(笑)
先ほどのAREA_ZZ_01.GTF_tex_159.dds同様、txNormalに適用したいファイルも、名前とサイズを調べて、同じ名前、フォーマット、サイズのファイルを作り、(1)のフォルダに入れればOKです。

よくわからないな~という人は、以前私が作ったSRPを雪道にするカスタムmodがあるので、ダウンロードしてみてください。
tky_srp_snow.7z - Google ドライブ

上記に書いてあるものを読みながら中身を見てもらうと、オリジナルのテクスチャへの差し替え方がわかると思います。

スキン適用前

スキン適用後(雪道)

別の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自体を作りこむ方が良いと思います。

fast_lane.aiの作成・調整

SRPで渋谷の街を走るのに、AI車両も走るといいなぁと思い、fast_lane.aiの作成をしたのでその覚書です。

最初にゲーム起動後のAIというアプリでfast_lane.aiの元を作ります。
作り方は、こちらの記事とかがわかりやすいでしょうか。
vorglc.blog.shinobi.jp

(注意)
この記事を書いている時点では、CSPのバージョンを0.1.79にしないと作成されたfast_lane.aiがblenderに取り込めませんでした。
(CSP0.1.80-preview346で作成されたfast_lane.aiはblenderで読み込めない)

そして、blender側にはアドオンを追加します。
追加するアドオンはこれです。
www.racedepartment.com

Blenderの2.8以降でないと動かないと書かれています。
私はBlender3.2を使っていますが、アドオンは動作しました。

アドオンを導入したら、メニューのインポートから、AC fast_lane.aiを選択します。

先ほど作成したfast_lane.aiをインポートします。すると、fast_lane.aiとfast_lane.ai_border_leftとfast_lane.ai_border_rightが登場します。

メインのラインがfast_lane.ai(黄色の線)で他二つがその左右のライン(オレンジの線)だと思いますが、左右のラインがぐちゃぐちゃです。
ここで、fast_line.aiのみ選択して、エクスポートします。ファイル名は別名にします。(fast_lane2.aiとか)
(注意)
ここで、元のファイル(fast_lane.ai)を上書きしても、うまく更新できません。別名保存で回避しています。
そしてエクスポートしたfast_lane2.aiを立ち上げ直したBlenderでもう一度インポートします。
すると今度は左右のライン(オレンジの線)は、メインのライン(黄色の線)に沿って、きれいに並んでいます。

サイドの線がきれいに並んでいることが確認出来たら、fast_lane2.aiをfast_lane.aiにリネームします。
(もともとあったfat_lane.aiは要らなければ消す、またはバックアップしておきます)

これで完成です。
ラインを作成するときに、ENABLE_DEV_APPS=1としていたところを、ENABLE_DEV_APPS=0に戻すのをお忘れなく。
(1を設定したまま走行会モードでゲームを始めると、激しくFPSが低下して、カクカクになったりします。(笑))

2024/5/11追記)
blenderを使ったラインの作成ですが、このアドオンを経由したaiファイルやサイドラインのデータが思い通りにエクスポートできないことが多くなりました。(何が原因なのかが良くわからないですが。)
現在は、shin956さんのこちらのブログのやり方で作成するようにしています。
shin956.hatenablog.com

AI Line Helperというpythonアプリの導入が必要ですが、fast_lane.aiおよびサイドライン(side_l.csvとside_r.csv)をゲーム中走行しながら作成することができるので、直感的でわかりやすいと思います。
特にサイドラインをトレースするときですが、峠の様に道のすぐ横が、崖やガードレールになっているような場合は、あまり端に寄りすぎず、少しマージンを持たせる感じで寄せて走るのが良いと思います。(バトルになった時、AI車がこの左右のラインを超えることがあるので)

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