ScriptableItemでTypeScriptを活用してみた
クラスター Advent Calendar 2022 3日目
この記事はCluster Creator KitのScriptable Itemの開発でTypeScriptを使ってみた紹介記事です。
TypeScriptはそのままではScriptable Itemで使うことができないので、一度ビルドツールを使ってJavaScriptに変換する必要があります。
この記事では変換にRollupライブラリを使い、TypeScriptからJavaScriptに変換してかつ複数ファイルを1つに纏めることも行います。
想定読者
JavaScriptの書き方は分かるけどNode.jsやTypeScriptの導入方法は分からない、導入してみたいという人。
この記事では書かない事
Cluster Creator Kitの使い方の説明
Cluster Creator Kitの使い方は公式ドキュメントやCreators Guideが非常に参考になるのでこの記事ではScriptable Item以外にはとくに触れません。
設定ファイルの説明
今回使ったTypeScriptやRollup(ビルドツール)は、設定ファイルを書く事でビルド方法のカスタムができます。
それらの設定方法を紹介をするとそれだけで1記事できてしまうので、今回は設定ファイルを含めたソースコードを公開することで、設定ファイルの説明は省略しています。
成果物
src/items/gun/main.ts
元のファイルの1つ
import { createThrottle } from "../../utils/throttle";
...
const shoot = (deltaTime: number) => {
const isUseDown = stateClient.getState("isUseDown");
const bulletChargeCount = stateClient.getState("bulletChargeCount") ?? 0;
if (isUseDown || bulletChargeCount <= 0) {
return;
}
shootThrottle(
() => {
$.log(`shoot ${bulletChargeCount}`);
cckClient.sendSignal("signal/action/shoot");
stateClient.setState("bulletChargeCount", bulletChargeCount - 1);
},
deltaTime,
SHOOT_INTERVAL,
);
};
...
これをビルドコマンドでJavaScriptにすると以下のようになります。
dist/gun.js
ビルド結果
'use strict';
const createThrottle = (key) => {
const stateClient = getStateClient(`throttle_${key}`);
return (fn, deltaTime, waitSecond) => {
var _a;
const currentPassedTime = (_a = stateClient.getState("passedTime")) !== null && _a !== void 0 ? _a : 0;
const nextPassedTime = currentPassedTime + deltaTime;
stateClient.setState("passedTime", nextPassedTime);
if (nextPassedTime >= waitSecond) {
stateClient.setState("passedTime", 0);
fn();
}
};
};
...
const shoot = (deltaTime) => {
var _a;
const isUseDown = stateClient.getState("isUseDown");
const bulletChargeCount = (_a = stateClient.getState("bulletChargeCount")) !== null && _a !== void 0 ? _a : 0;
if (isUseDown || bulletChargeCount <= 0) {
return;
}
shootThrottle(() => {
$.log(`shoot ${bulletChargeCount}`);
cckClient.sendSignal("signal/action/shoot");
stateClient.setState("bulletChargeCount", bulletChargeCount - 1);
}, deltaTime, SHOOT_INTERVAL);
};
...
今回試してみたソースコードは https://github.com/warabiiiii/script-sample に置いてあります。
以下今回のソースコードを試すための環境構築手順を紹介します。
導入手順
Node.jsの導入
TypeScriptやRollup(ビルドツール)を使うために、JavaScript実行環境のNode.jsをインストールします。
今回はもっとも単純な方法である公式サイトから直接ダウンロードする手順でインストールをします。バージョンは推奨版のv18.12.1を使います。
Node.js公式
ターミナルでnode --version
とコマンドを入力した時にバージョン情報を出力できれば、インストールが成功しています。
node --version
> v18.12.1
必要ライブラリのインストール
以降のコマンドは作業ディレクトリをpackage.jsonが存在するディレクトリ(今回の例ではscript-sample/Assets/Script
)にした状態で行います。
npm install
コマンドを実行することでpackage.jsonで設定済みの各種ライブラリをインストールします。
npm
コマンドはNode.js導入時に追加されているはずなので、npmコマンドが見つからない時はNode.jsの導入になんらか問題が起きている可能性があります。
$ npm install (setup)
added 198 packages, and audited 199 packages in 26s
77 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
コマンドの実行が完了するとnode_modules
ディレクトリに各種ライブラリがインストールされています。
$ ls ./node_modules
@clustervr
@clustervr.meta
@eslint
@eslint.meta
...
ビルド
npm run build
コマンドを実行することでsrcディレクトリのファイルがdistディレクトリにビルドされて出力されます。
$ npm run build
> build
> rollup --config
src/items/gun/main.ts → dist/gun.js...
created dist/gun.js in 171ms
コマンドが完了するとdistディレクトリに成果物のJavaScriptファイルが作られます。
Scriptable Itemとの紐付け
生成されたJavaScriptファイルをScriptable Itemと紐づけます。
Scriptable Item componentのSource Code Asset
にAssets/Script/dist/gun.js
を設定することで、生成されたJavaScriptファイルをScriptable Itemと紐づけることができます。
Gun Object | Scriptable Itemとの紐付け |
---|---|
ワールドアップロード
clusterにワールドをアップロードすることでスクリプトの動作が確認できます。
今回作ったスクリプトは「クリック長押しでチャージした分だけ弾を撃つシグナルを送る」ものでしたが、正常に機能していることが確認できます。
シグナルを受け取って弾丸を生成する方法はCreatorsGuideの記事が参考になります。
おわりに
あっさりめの記事でしたが、今回はScriptableItemのコードを書く時にTypeScriptを活法する例を紹介してみました。
JavaScriptはエコシステムが非常に充実している言語で、今回紹介したTypeScriptやRollup以外にも様々なライブラリがあります。
(有名どころではコードフォーマッターのPrettier、LinterのESLint、テスティングフレームワークのJestなどなど)
それらを活用してScriptableItemの開発もどんどん加速させていきましょう👍
おまけ1 buildコマンドは何をしている?
導入手順で紹介したnpm run build
コマンドはpackage.jsonに書いたカスタムコマンドを実行するもので、中ではビルドツールのrollupを呼び出しています。
"build": "rollup --config"
おまけ2 ファイルの変更を検知して自動でbuildする
rollupはwatch
機能が実装されていて、ビルドの対象ファイル(今回の例ではsrcディレクトリ内のファイル)を更新した時に自動で再ビルドを動かせます。
"watch": "rollup --config --watch"
package.jsonにwatchコマンドを追記してnpm run watch
を実行すると、ファイルを監視する状態になりsrc内のファイルを変更すると自動でdistディレクトリも更新されるようになるので、都度npm run build
を実行しなくてよくなります。
Discussion