🍣

Cluster HUD v2をやってみた

2024/10/02に公開

HUD(Head up Display)v2をやってみた

初めに

2024年7月8日 CCK 2.18.0でPlayerScriptとCluster HUD v2が公開されました。
プレイヤー個別の制御をどのように処理するか、という整理がおそらくできたそうです。
これによってPlayerScriptによってプレイヤーに関する処理をワールド全体の同期とは別の実行コンテクストで処理するようになったみたいです。
この記事ではHUD v2によって、プリント俱楽部みたいなことができるワールド制作を作るまでの経緯を記録したいと思います。

モチベーション

ScriptableItemとPlayerScriptの違いはワールド全体の同期のためのコンテキストと別の実行コンテクスト(自分の端末の状態)の違いということです。イノベーターによるPlayerScriptの導入済ワールドを見てワールド制作でできることが広がったことは分かったのですが、それを自分も動かしてみたいという気はありませんでした。
今回は、もともとonInteractでPlayerHandleの情報をonUpdateで再利用したい、と思っただけだけでした。しかし、動作確認した範囲ではonInteractのPlayerHandleを配列に保持すること自体がうまくいかなくて、、、一日を溶かして悲しい気持ちになりました。プレイヤー単位の処理についてはPlayerScriptで表現する、、、という記憶が頭の片隅にあったので、今回記録を残していきたいと思いました。

絶望と希望

まず初めに、「PlayerScript」で検索してヒットした記事
【ベータ機能・サンプル付き】PlayerScriptで「ボタンで出せるアバターモーション」をつくるを読みました。
ほかにも【ベータ機能・サンプル付き】Cluster HUD v2で銃の構え方の指定・いつでもリロードできるようにしてみようという記事も確認しました。
ガッと眺めたとき、全容知識が足りな過ぎて、記事を見ただけでは実現する見通しが立たちませんでした。(イノベーターたちはこの状態でもトライしているなんてすごいなぁ。。。)
参考ページ、トラブったみたいな記事は見かけなかったのは、記事通り頑張ればトラブることはないのだと思うのですが、マジョリティの一員のぼくには不安しかありません。。。この苦しい気持ちはにならないのでしょうか。

記事ではなくYoutubeで検索したり、ワールドで検索したり、その結果ワールド制作や実装の見通しが立ちそうになりました。
【Clusterチュートリアル】PlayerScript① ボタンで出せるアバターモーション
【Clusterチュートリアル】PlayerScript② 任意のクラフトアイテムを呼び出す
好きなクラフトアイテムを呼び出す
CCK勉強会PlayerScriptで遊ぼう
luster Game HUD v2の始め方(LT資料とその補完)
Cluster Game HUD v2 はじめよう

(我々人類は、神の領域に達することはできません。識字率の低い時代ではその尊厳をテキストで伝道することはできず、絵としてあるいはステンドグラスで伝達してきました。そんな神の領域をテキストして低次元に射影すると、民衆の次元に落とすことをよしとしない人もいるでしょう。しかし、僕は声を大にしていいたいです。ありがとうございます。日本に複合型宗教があってよかったです。八百万の神々を信仰してよいなら、GoT(Gods of Things)が許されるなら、導いてくれた人々を崇め、仰いで、信じています。
あぁ。神よ、今日もありがとう。)

PlayerScript入門

関係図

まずPlayerScriptというものの立ち位置です(僕の理解)。

アイテム関係図

PlayerScript付随したアイテムを利用するにはClusterからIDを指定して生成しないといけないようです(僕の理解)。

Item2に登録するClusterScript2は下記に登場するAttachFollowingItem.jsのことです。基本的にこのファイルはクラフトアイテムとして登録したitem1のアイテムIDを指定し、item1のに設定したClusterScript1(FollowingItem.js)のonReceiveを経由してプレイヤーIDをPlayerScriptに登録しています。

環境構築

【ベータ機能・サンプル付き】Cluster HUD v2で銃の構え方の指定・いつでもリロードできるようにしてみよう にある通り、[サンプルアイテム)(https://creator.cluster.mu/wp-content/uploads/2024/07/PlayerScript_AvatarMotion.unitypackage)を動かしてみます。

ベータ版導入の環境構築まで

もう当たり前になっていると思いますが、手順でないページへのリンクを張って、それを見て頑張れって普通つらいと思います。
Cluster Creator Kitがv2.18.0以上が要件ですが、最新のテンプレートClusterCreatorKitTemplateであれば十分なはずです。(Unityのメニュバー[ウィンドウ]>[パッケージマネージャー]のパネルに、「パッケージ:~」と文字があるコンポーネントリストを「パッケージ:マイレジストリ」にします。↑のテンプレートであればCluster Creator Kitが含まれているので、最新バージョンに更新できます)

ベータ機能を有効にするにはUnityのメニュバー[Cluster]>[設定]にある「ベータ機能を有効にする」にチェック☑を付けます。(この環境のワールドは、すでに公開している正式版のワールドにアップロードできません。アップロードする場合は[Cluster]>[ワールドアップロード]において、「新規作成」ボタンを押して[beta]と名の付く作成済みワールドを用意しておく必要があります(2敗)。アップロードにはサムネイルの画像が必要です)

このUnityのシーンに↑でダウンロードできるサンプルアイテムPlayerScript_AvatarMotion.unitypackageをドラッグアンドドロップ(D&D)してインポートします。

HUD v2(Head Up Dispay)を有効にする

World Runtime Settingコンポーネントをワールドに配置します。
Unityのヒエラルキーで右クリックして空オブジェクト作成し、そのオブジェクトのインスペクターで「コンポーネントを追加」ボタンを押してWorld Runtime Setting(スクリプト)を選択します。このオプションで「Use Cluster HUD v2」にチェック☑を付けます。
この段階でワールドをアップロードすると、ワールド内でLeft Controllボタンが有効になり、しゃがむことを確認できるはずです。

サンプルPlayerScriptを動かす

プレイヤーに追従するアイテムをクラフトアイテムとしてアップロードする

(一般的な人類はもしかすると何も疑問に思わないかもしれませんが、僕みたいな心配性からすると、
HUD v2のあとに"プレイヤーに追従するアイテムをクラフトアイテムとしてアップロードする"とかいう項目が来ると意味が分からな過ぎて匙を投げたくなります。この手順はPlayerScriptを実装するにあたり、僕の寿命を削る必要があるのだろうか、と。。。あと、クラフトアイテムアップロード手順への直リンクが存在しないのがつらい。)
どうやら、PlayerScriptを付随したアイテムは、Unityのヒエラルキーに配置してワールドにアップロードせず、Clusterのクラフトアイテムとして登録しておくようです。そのあと、Unityのヒエラルキーに配置した別のアイテムからPlayerScriptを付随したアイテムを生成して利用する運用らしいです。(勝手な想像ですが、プレイヤーのコンテキスト(プレイヤー単位でコールバックを呼ぶのであろう)内に登録する必要があると思われ、このコンテキストはUnityのCCKコンポーネントには用意してくれないようです)

Unityのメニュバー[Cluster]>[クラフトアイテムアップロード]で「クラフトアイテムアップロード」タブを開きます。UnityのプロジェクトでPlayerScript_AvatarMotionフォルダーにあるFollowingItemを「クラフトアイテムアップロード」にD&Dし、「ベータ機能利用アイテムとしてアップロード」ボタンを押します。

アップロード時に良く失敗したので追記します。
サンプルコードと同様に、subnodeにCubeを設定しておき(多分Mesh Rendererはoffにして運用するはず)、itemの項目名とサイズは適当にしておかないとアップロードに失敗します。(1敗)

アップロードしたクラフトアイテムを使う

このアップロードしたアイテムはメタバースプラットフォームで確認できるはずです。(しかし、ウェブブラウザ上でアップロードしたアイテムのIDはわからないです。つらい)
このアイテムのIDの確認方法はUnityのメニュバー[Cluster]>[クラフトアイテムの情報取得]から、アップロードしたアイテムの項目名一覧からわかります。(クラフトアイテムの情報取得の一覧で文字列検索できません。つらい。)
このアイテムのIDをUnityのプロジェクトでPlayerScript_AvatarMotionフォルダーにあるAttachFollowingItem.jsのItemTemplateIdの引数に指定します(UUID形式の文字列)
new ItemTemplateId("f32509f9-afc9-4d9e-b775-6b66fa2fdd0c");

UnityのプロジェクトでPlayerScript_AvatarMotionフォルダーにあるPlayerScriptAttacherというPrefabをヒエラルキーに配置し、[beta]と名の付く作成済みワールドをアップロードします。
Clusterアプリで確認すると、(PC版では)Rボタンが有効になっていることを確認できます。プレイヤーの足元にこのアイテムの表示Cubeが追従します。

AttachFollowingItem.js

(上の関係図でItem2、サンプルPlayerScriptAttacherアイテムに登録されているもの。)
ワールド内の未登録のプレイヤーに対し、プレイヤーの位置と向きに合わせて↑で指定したIDアイテムを生成し、そのアイテムにメッセージタイプ"RegisterPlayer"と playerハンドルという引数メッセージを送っているだけです。AttachFollowingItemというファイル名だが、onReceiveでメッセージタイプRegisterPlayerにplayerハンドルを受け取るような、アイテムIDを受け付けるファイルであるようです。
ItemTemplateId
createItem
send

FollowingItem.js

(上の関係図でItem1、サンプルFollowingItemアイテムに登録されているもの。)
メッセージタイプ"RegisterPlayer"から playerハンドルを受け取って、PlayerScriptにplayerハンドルを設定しています。

setPlayerScript

onUpdateでアイテムの位置を変更しているようです。アクションゲームでプレイヤーに攻撃できるとかいうメカニクスを作らないなら、アイテムがプレイヤーに追従している必要はないと思われます(どうせ表示用のCubeは非表示にするでしょう )

PlayerScriptSample.js

(上の関係図でItem1、サンプルFollowingItemアイテムに登録されているもの。)
HUD v2の根幹となるコードがあります。
ボタンの表示

_.onStart(() => {
   _.showButton(3, _.iconAsset(""));
});

ボタンを押された時の処理

_.onButton(3, (isDown) => {
    if (isDown) {
        // ボタンを押された時の処理
    }
});

サンプルでは、アニメーションの実行はPlayerScriptSampleで実装し、audioの実行はFollowingItemで実装しています。
showButton

showButton インデックス キーアサイン
0 左クリック
1 右クリック
2 Eキー
3 Rキー

ということで、23個もボタン表示できないらしいです(つらい。)

独り言

AttachFollowingItem.jsはほとんどのケースではファイルをコピペしてアイテムIDだけ書き換えることになると思われます。
このクラフトIDだけ書き換える神ツールがあるので、おそらくファイルをコピペは不要になると思います。
https://github.com/malaybaku/ClusterScriptExtensions/releases
(素晴らしすぎる。これがMITライセンスで公開されていることに感謝しかないです。僕は現時点で利用していませんが、近い将来謹んで課金することになりそうです。 ClusterScriptExtensions )

この記事の立ち位置と個人開発

たとえ僕の記事が読みにくいとか、このとおりにやっても機能しないことがあるかもしれませんが、無いよりはマシだと思うので、一応公開します。個人的にやりたいことは下に続きます。誰かの二番煎じだと思いますが、僕の人生の時間つぶしに記事を書くことをお許しください。

PlayerScript開発

結局僕が用意したいメカニクスは、数十個のプレイヤーのアニメーションを切り替えたいだけです。
RキーをトグルとしてアニメーションのOn/Offを切り替えるようにし、
EキーをアニメーションのIDを切り替えるようにしてみたいと思います(2024/09/29)

VRMに動きをつけてみたで記録していますが、Humanoid Animationを含むFBXを準備する必要がありそうでした。
ポーズ固定の静止した(VrmPosingDesktopで1つだけ記録した)ポーズでは、アニメーションとして登録できず、クラフトアイテムとして登録すると失敗していました(N敗)。ほかにはFBXをプロジェクトに配置したときにアニメーションタイプを「ヒューマノイド」に設定しないといけないのですが、よく忘れます(2敗)。

PlayerScriptでエモーションを切り替える

まったく新規性もないのですが、PlayerScript側のアイテムとソースの一部を添付しておきます。

let motionNo = 0;

const motions = [
    _.humanoidAnimation("Animation0"),
    _.humanoidAnimation("Animation1"),
    _.humanoidAnimation("Animation2"),
    _.humanoidAnimation("Animation3"),
    _.humanoidAnimation("Animation4"),
]
const motionSize = motions.length;

// ...

_.onButton(2, (isDown) => {
    if (isDown) {
        ++motionNo;
        if (motionNo >= motionSize) {
            motionNo = 0;
        }
        _.log(`onButton motionNo: ${motionNo}`);
    }
});

_.onButton(3, (isDown) => {
    if (isDown) {
        const isCurrentPlayingMotion = isPlayingMotion;
        if (!isCurrentPlayingMotion) {
            // メッセージを送ってアイテムから音を鳴らす
            _.sendTo(targetItem, "PlaySound", null);

            // モーション再生開始
            motionTime = 0;
        }

        isPlayingMotion = !isCurrentPlayingMotion;
    }
    _.log(`onButton isPlayingMotion: ${isPlayingMotion}`);
});

_.onFrame(deltaTime => {
    // モーション再生
    if (isPlayingMotion) {
        _.log(`onFrame motionNo: ${motionNo}`);

        motionTime += deltaTime;
        const motion = motions[motionNo];
        isPlayingMotion = playMotion(motion, motionTime);
    }
});

エモートとアイコン

https://www.mixamo.com/#/


エモートを作ることはできるのですが、mixamoにあるデータを使うようにしました。
アイコンをクラフトアイテム選択で切り替えるようにしようとし、うまくいきませんでした。(N敗)
下記の通り、アイコンで利用するには制約がいくつかあるのですが、、、、

アイコン画像は透過画像、かつ正方形であることを前提に扱われます。この条件に合致しないアイコンの表示結果は保証されません。
アイコン画像は表示サイズが決まっているため、必ずしも高解像度である必要はありません。1辺256px以下の画像を指定することを推奨しています。

2024/10/13時点でクラフトアイテムでiconAssetListは未対応、とのことでした。(vinsさん、ありがとうございました。)

細かいトラブルですが、エモートを付けたクラフトアイテムアップロードで
「HumanoidAnimationListのキーフレームが多すぎます。現在地: #### 最大値:50000」というエラーが出ます。このエラーが出たらキーフレームが多いことはわかるのですが、どうしたらいいのでしょう(つらい)。Mixamoではアニメーションを選択すると、タイムラインに##/

とフレーム数がでるので、
が小さいほうがキーフレームが少ないと予想できます。またダウンロードしたfbxファイルサイズが小さいとキーフレームが少ないと予想できます。
僕の場合アイテムにアニメーションを10個登録していました。およその目安として、10個いずれも1000KB以下のサイズであればこのキーフレームの最大値を超えないくらいになるようです。(どんぶり勘定)

Discussion