2021/7/11追記)
v0.23で変更が入ったので本文を修正しています。
2021/7/31追記)
ダウンロード用のサンプルファイルを置きました。+軽微な修正。
BeamNG.driveを始めて10ヵ月、ついに私もMod作成に手を出してしまいました…!!
ということでMod作成について今回から連載していきたいと思います!!(目標月1更新…)
BeamNG.driveには車やシナリオ、スキンなど、様々な種類のModがありますが、今回はUIのModについてです。
1.UIとは?
ここでいうUIは、タコメーターやナビゲーションメニューといったプレイ中に画面に表示されるもののことです。
技術的にはJavascript(AngularJS), HTML, CSS, SVGといったWEBのフロントエンドっぽいもので作られています。
「「なんか難しそう、、、」」
と感じるかもしれませんが、大丈夫です。
オリジナルのUIをコピペしていけば大体何とかなります。
また、BeamNG.drive特有のこと以外は、ググれば9割がた日本語記事が出てくるので、そういった意味でも作成のハードルは低いかと思います。
(WEB系で働いている人が多いのでしょうね…)
2.Mod作成時の環境(使用ソフト等)
今回は初回なのでMod作成時の環境(使用ソフト等)についても紹介しておきます。
※ここは割と好みの問題なので、あくまで参考程度です。(宗教戦争の意図は一ミリもありません)
UIのMod作成で使用するのは以下の2つです。
- エディタ(必須):HTML等を編集する
- SVG編集ソフト(あれば便利):UIのグラフィカルな部分を作成する
エディタ(VS Code)
エディタはVS Codeを使用しておけばまず間違いありません。
無料ですし、HTMLやJSにデフォルトで対応しています。
また、日本語化が容易というのも最高です。つまりVS Codeが神です。VS Codeを信じる者は救われます。
ダウンロードは以下のページから行えます。
Download Visual Studio Code – Mac, Linux, Windows
※OS・アーキは適切なものを選択してください。
※User/Systemはインストール先がユーザ毎かPC全体かの違いです。通常はユーザで問題ないと思います。
ダウンロード後はインストーラに従っていくだけの簡単なお仕事です。
インストールが完了したら、最後に日本語化を行います。
これでエディタ(VS Code)の準備は完了です。
SVG編集ソフト(Inkscape)
続いてSVG編集ソフトです。
簡単に言えばペイントソフトで、SVG形式のファイルの出力・編集に対応しているソフトです。
こちらは必須ではありませんが、グラフィカルなメーター等を作成したい場合はあった方が絶対便利です。
今回はInkscapeというソフトをご紹介します。
これはOSSで無料で使用可能なソフトになっています。
(BeamNG.driveのフォルダを漁ってみた感じだと、BeamNG.drive開発チームもこれを使用してるっぽいです)
ダウンロードは以下から行います。
https://inkscape.org/release/
※OS・アーキは適宜選択してください。
これもインストーラでポチポチやっていくだけなのでインストールで困ることは特にないと思います。
日本語化もインストール時に設定可能です。
UIのMod作成で役に立つソフトの紹介は以上です。
次はいよいよMod作成について説明していきます。
3.はじめてのUI Mod
3-1 フォルダ作成
UIのModは以下のフォルダに配置する必要があるので、まずはフォルダを作成してください。C:\Users\<ユーザ名>\AppData\Local\BeamNG.drive\<バージョン>\ui\modules\apps\<Mod毎フォルダ>
Modフォルダに作成してもいいですが、開発中はこっちで作成し、アップロードする段階でMod用のZIPファイルを作成するほうが楽な気がします。
「Mod毎フォルダ」 内の構成は以下のようになっています。
- app.js(必須):UIのメインのファイル。動作を定義するコードが書かれている。
- app.json(必須):UIの大きさ等を設定するファイル
- app.png(任意):UI選択画面でのアイコン用の画像
- xx.json(任意):情報を保持したい場合はJSONファイルに保存可能
- xxx.html(任意):HTMLはapp.js内に記載可能だが、別ファイルにすることも可能
- xxx.svg(任意):SVGはapp.js内に記載可能だが、別ファイルにすることも可能
3-2 ファイル作成
次にModのファイルを作成していきます。
まずはapp.jsとapp.jsonがあれば十分なので、この2つのサンプルを置いておきます。
ダウンロードする場合は以下のzipファイルをご利用ください。
動作確認済みなので、UI Mod作成のベースにご利用ください。
(画面上にボタンが表示され、クリックするとカウントが増えていくだけの簡易なUIです)
app.js
angular.module('beamng.apps')
.directive('testApp', [function () {
return {
/* 画面(HTML)の部分。
*
* {{}}で囲った変数は↓の関数内でscope.XXXでアクセス可能。
* class="bngApp"を指定すると、半透明の背景等のデフォルトスタイルが適用される
*/
template: '<div class="bngApp"><button ng-click="hello()">Click Me</button><span>count: {{ clickCount }}</span></div>',
replace: true,
restrict: 'EA',
// この関数内にやりたいことを書く。
link: function (scope, element, attrs) {
// 例:ボタンがクリックされるとカウント
scope.clickCount = 0;
scope.hello = function () {
scope.clickCount += 1;
};
}
};
}])
コード内にコメントしているので解説は省略します。
app.json
{
"name" : "test",
"author": "test",
"version": "0.1",
"description": "テスト用",
"directive": "testApp",
"domElement": "<test-app></test-app>",
"css": {
"width": "150px",
"height": "150px",
"top": "200px",
"left": "200px"
}
}
“name“, “aouthor“, “version“, “description“は英語のままなので省略します。適当な値で特に問題ないです。
※”name”が他のUIと被っていると一覧に表示されないので注意。
“directive“は、app.jsの2行目directiveと合わせる必要があるので注意しておいてください。
“domElement“は、”directive“のlisp-caseで指定してください。上記の例の場合、testApp→test-appになります。
※”directive”, “domElement”も他のUIと被らないようにしたほうが良い。
“css“は、初期サイズを指定します。上記の例ではピクセル単位で指定していますが%単位で指定することも可能です。
表示イメージ
上記のファイルをUIのフォルダに配置し、BeamNG.driveを起動すると、以下のようにUIに追加されるようになります。
これをクリックして画面に表示させると以下のようになるはずです。
これで「はじめてのUI Mod」は完成です。
ここからは、これをベースに機能追加をしていくことになると思います。
なので次は作成時に役立つヒント・サンプルコードを説明していきます。
これは作りたいUIによって大きく変わってくる部分ですが、この記事ではなるべく一般的・基本的な内容を取り上げていきます。
4.Mod作成のTIPS~基本編~
4-1 動作確認(デバッグ)
まずは作成したUIの動作確認の方法を紹介します。
例えば、上記の例で、scope.clickCount += 1;
をscope.clickCount += 10;
に変更し、クリックするたびに10ずつカウントが増えていくようにしたとします。
この時、BeamNG.drive上で動作確認をしたくなると思うのですが、ファイルを書き換えただけだと、BeamNG.drive側のUIには反映されません。
(これに気付かず3兆年くらい悩んだ)
ファイルを編集した後、UIをリロードする必要があります。
方法自体はとても簡単で、F5キーをクリックして “Reload UI” を実行するだけです。
※F5が機能しない人は、メニューの”Options” > “Controls”から”General Debug” > “Reload UI”のキーを設定してください
また、もっと詳細なエラーログを見たい場合は、以下が使えます。
・UI Console
UI開発時に必要なアレコレが詰まったコンソールになります。
“Ctrl + U”キーで開くことができます。
“Cosole”の部分でエラーログが確認できます。
・System Console
BeamNG.drive全体のシステムコンソールになります。
“^”キーで開くことができます。
こちらにしか出ないエラー等もあるので、私は基本的に両方とも表示した状態でデバッグしています。
4-2 オリジナルのUIを参考にしよう
序盤でも少し触れましたが、UIについては公式のUIのコードが見える場所に置いてあるのでそれを参考にすることができます。
UIを作成する際は、作りたいModに近いUIのファイルをコピペするのが簡単だと思います。
ちなみにBeamNG.drive公式のUIは以下にあります。
C:\Program Files (x86)\Steam\steamapps\common\BeamNG.drive\ui\modules\apps
(インストール方法によって上側が違うかもしれないので適宜読み替えてください)
4-3 HTMLのファイルを分ける場合
HTMLを別ファイルに分けた場合、パスは以下のように設定してください。
angular.module('beamng.apps')
.directive('testApp', [function () {
return {
templateUrl: '/ui/modules/apps/「appのフォルダ名」/「ファイル名」.html',
// こっちは不要
// template: '<div class="bngApp"><button ng-click="hello()">Click Me</button><span>count: {{ clickCount }}</span></div>',
~~以下省略~~
“template”ではなく”templateUrl”で指定する必要がある点に注意です。
(これに気付かず5000兆年くらい悩んだ)
4-4 SVGファイルを分ける場合
SVGを別ファイルに分けた場合、パスは以下のように設定してください。
angular.module('beamng.apps')
.directive('testApp', [function () {
return {
template: '<object type="image/svg+xml" data="/ui/modules/apps/「appのフォルダ名」/「ファイル名」.svg"></object>',
~~以下省略~~
4-5 bngApiを使用する場合
bngApiはBeamNG.driveのAPIでBeamNG.driveの情報取得・制御が可能です。
※bngApiの詳細については以下をご参照ください。
https://wiki.beamng.com/Lua:Reference
UIで使用する場合は以下のように記述します。
angular.module('beamng.apps')
.directive('testApp', [function() {
return {
// 画面(HTML)の部分。{{}}で囲った変数は↓の関数内でscope.XXXでアクセス可能。
template: '<div class="bngApp"><button ng-click="hello()">Click Me</button><span>count: {{ currentTrafficNum }}</span></div>',
replace: true,
restrict: 'EA',
// この関数内にやりたいことを書く。
link: function (scope, element, attrs) {
// 例:ボタンがクリックされるとトラフィックの数を取得する。
scope.currentTrafficNum = 0;
scope.hello = function () {
bngApi.engineLua('extensions.gameplay_traffic.getNumOfTraffic()', (result) => {
scope.currentTrafficNum = result;
});
};
}
};
}])
4-6 UIをリアルタイムに更新したい場合
ここまでは、「ボタンがクリックされた時に○○」というサンプルを紹介してきました。
しかし、「スピードメーターのようなUIで、リアルタイムにUIを更新したい」ということがあると思います。
その場合は、以下のように記述することでUIをリアルタイムに更新することが可能です。
angular.module('beamng.apps')
.directive('testApp', [function() { // StreamsManagerが必要
return {
// 画面(HTML)の部分。{{}}で囲った変数は↓の関数内でscope.XXXでアクセス可能。
template: '<div class="bngApp"><span>{{ currentWheelSpeed }}</span></div>',
replace: true,
restrict: 'EA',
// この関数内にやりたいことを書く。
link: function (scope, element, attrs) {
// StreamsManagerに欲しいstreamの値を設定することでstreamへのアクセスが可能
var streamsList = ['electrics'];
StreamsManager.add(streamsList);
// streamの更新が発生したタイミングで実行される(=リアルタイムに実行される)
scope.$on('streamsUpdate', function (event, streams) {
scope.$evalAsync(function () { // SVG描画する時evalAsyncなくても反映されるんだけどなんでなん。。。Agnular詳しい人教えて。。。
scope.currentWheelSpeed = streams.electrics.airspeed;
})
});
scope.$on('$destroy', function () {
StreamsManager.remove(streamsList);
});
}
};
}])
上記はstreamを使用する例として書いていますが、streamを使用しないUIをリアルタイムに更新したい場合も同様の書き方で問題なさそうです。
(公式のUIでそういう書かれ方をしていた)
終わりに
今回はここまでです。
UI Mod作成の基本的な部分は一通り網羅できたと思うので、簡単なModであればもう作れるようになっているのではないでしょうか。
次回、応用編では、より細かい部分を解説していきたいと思います。
以上です。
参考
公式ドキュメント
https://documentation.beamng.com/modding/ui/app_creation/
wiki(bngApi(Lua), streamについて)
https://wiki.beamng.com/Lua:Reference
https://wiki.beamng.com/Streams
コメント / COMMENT
ダウンロードした3dデータをbeamNG用modに作り直すにはどうしたらいいですか?
返信遅くなり申し訳ありません!匿名コメントは通知が来ないのでスルーしてしまっていました…
匿名コメントだとコメ主さんにも返信の通知が届かないのでお問い合わせフォームをご利用いただければと思います!
(コメント欄が分かりにくいですよね…注釈を追記しておきました、すみません)
一応質問に回答しておくと、3Dデータを何に使うかによって異なります。
①マップ上の破壊不能オブジェクト(建物等)として使う場合
→daeファイルをマップのフォルダに置いてアセットブラウザから選択すればOKです。(スキンの設定とかは別途必要ですが)
②jbeam(車両等)として使う場合
→かなり複雑な操作が必要で、概要だけ書くと以下の感じです。
・3Dデータのノードが三角または四角のみで構成されるように改造
↓
・Blenderにjbeam exporterプラグインを使用してjbeam出力
↓
・jbeamファイルを調整(ここが一番面倒)
↓
・jbeam、スキン、コンフィグの各ファイルを車両フォルダに配置