見出し画像

Creator Kit製ワールドを複数のUnityシーンに分けて構成できる「SubScene」、ベータ機能「テキスト入力・出力」「メタデータ取得」が使えるように 他【Cluster Creator Kit v2.6.0リリース】

こんにちは、プロダクトマネージャーの Smith です。

メタバースプラットフォーム cluster では、クリエイターのみなさんの創造力をより加速できるように制作環境の改善を行っています。
この記事では Cluster Creator Kit v2.6.0のリリースで利用できるようになった新規機能や変更点について紹介します。


機能追加・改善

SubScene

clusterのワールドは Unity のシーンで表現されており、これまでシーンは1つしか使うことができませんでした。
SubScene は、Creator Kit 製ワールドを複数の Unity シーンに分けて構成させられます(ハロクラで「ワールド分割ロード」として紹介した機能です)

Unity のシーンについてはこちらの Unity ドキュメントを参照して下さい。

SubScene として指定したワールド要素は、必要に応じてロードされるようになります。
これにより、入室にかかる時間を減らしたり、ワールドのメモリ消費量を減らしたりできます。
SubScene はコンポーネントとして提供されており、この機能を用いることで広大なワールドも実現できます。

SubSceneの制約
SubScene 関連のコンポーネントにはいくつかの制約があるため留意して下さい。

  • SubScene で設定する Unity シーンには Item, Operation, PlayerGimmick, PlayerLocalUI を含めることはできません

  • SubScene で設定する Unity シーン内のワールドコンポーネントは基本的には動作しません

  • 後述する SubSceneSubstitutes と Item は同時にアタッチできません

使い方
SubScene は Unity のシーンで表現されており、ロード制御はコライダーを用いています。
ワールドを分割したい単位で Unity シーンを作成し、SubScene コンポーネントで指定することでロード制御ができます。
Unity Editor 上では、メインシーンに対して Additive でシーンを追加すると、全体像を見ながら作業できます。
シーンファイルをヒエラルキーにドラッグするか、シーンファイルを右クリック > Open Scene Additive  を選択することで Additive にシーンが追加できます。

SubScene の具体的な指定方法は下記のとおりです。

  • 任意の GameObject に SubScene コンポーネントをアタッチします

    • 何らかのコライダーがアタッチされている必要があります

    • SubScene コンポーネントをアタッチするとコライダーの isTrigger がオンに設定されます

      • 必ずSubSceneコンポーネントより先にコライダーをアタッチしてください

  • SubScene コンポーネントの Scene フィールドに、分割した Unity のシーンを指定して下さい

画像では CapsuleCollider を用いていますが、任意のコライダーで問題ありません

また、ロードされていないシーンの代替として任意の GameObject を配置することもできます。
これは *LOD のような用途として用いることができます。

下記の手順で設定できます。

  • SubScene が表示されていない時に、代わりに表示したい GameObject に SubSceneSubstitutes コンポーネントをアタッチ

  • SubSceneSubstitutes の SubScene フィールドに代替表示の対象となる SubScene コンポーネントがアタッチされている GameObject を指定

  • SubScene が表示されていない時に、代わりに表示したい GameObject に SubSceneSubstitutes コンポーネントをアタッチ

  • SubSceneSubstitutes の SubScene フィールドに代替表示の対象となる SubScene コンポーネントがアタッチされている GameObject を指定

以上が SubScene の基本的な利用方法です。

SubScene は複数を同時に扱うことができます。
下記の画像のような構造の SubScene を利用したワールドがある場合、シーンのつなぎ目で前後のワールドをロードさせるような挙動にできます。
MainScene => SubScene 1 => SubScene 2 の順にプレイヤーが移動した場合、下記のようなロード処理が行われます。

  • MainScene にスポーン、他のシーンはまだロードされていない

  • MainScene と SubScene 1 の間の通路に侵入、SubScene 1 がロードされる

  • SubScene 1 と SubScene 2 の間の通路に侵入、SubScene 2 がロードされる

  • 通路を超えて SubScene 2 の部屋に入りきると、 SubScene 1 が破棄される

つなぎ目となる通路のような場所は MainScene で保持するか、ロード前後のシーンで持っておくとよいでしょう。

*LOD: Level of Detail、 カメラからの距離に応じて描画方法を変化させる技法、あるいはそのための機能です。 LOD をうまく設定することによってワールドの負荷を軽減できます。

Speaker コンポーネントの AudioSource の dopplerLevel の初期値変更

Speaker コンポーネントをアタッチした際の AudioSource の dopplerLevel が 0 に変更になります。
これまで意図せず 0 以外の数値になる場合があり、VR でのアバターのワープ移動などで音声が意図した聞こえ方になっていない場合がありました。
初期値の変更のみであり、引き続き任意で 0 以外の値に設定できます。

ベータ機能

正式リリース前の機能を前もってお試しいただける機能です。詳細は下記のページをご覧ください。

テキスト入力

テキスト入力はユーザーに任意の文字列入力を要求できる機能で、スクリプト API として提供されています。
API は任意の PlayerHandle インスタンスから実行可能で、実行すると PlayerHandle が管理するユーザーに対してテキスト入力を要求します。
ユーザーがテキスト入力を受け付けられる状態であればテキスト入力ダイアログが表示されます。

requestTextInput(meta: string, title: string): void
// 実行例
$.onInteract((playerHandle) => {
  playerHandle.requestTextInput("name", "こんにちは。あなたの名前は?");
});

テキスト入力要求に対して何かしらの結果が返ってくると、 ClusterScript ($) の onTextInput に登録したコールバックが実行されます。

onTextInput(callback: ((text: string, meta: string, status: TextInputStatus) => void)): void

入力された文字列は text 引数で取得できます。
テキスト入力要求結果がどのようなものだったかは、status 引数 の TextInputStatus から知ることができます。

$.onTextInput((text, meta, status) => {
  switch(status) {
    // テキスト入力が送信された場合
    case TextInputStatus.Success: ...
    // テキスト入力ダイアログが表示できない場合
    case TextInputStatus.Busy: ...
    // テキスト入力ダイアログがキャンセルされた場合
    case TextInputStatus.Refused: ...
  }
});

スクリプト上で複数のテキスト入力要求を扱っている場合、それぞれを見分けるには requestTextInput のmeta 引数を識別子として用いてください。

$.onInteract((playerHandle) => {
  $.state.player = playerHandle;
  playerHandle.requestTextInput("first_question", "...");
});

$.onTextInput((text, meta, status) => {
  if (meta === "first_question") {
    $.state.player?.requestTextInput("second_question", "...");
    return;
  }
  ...
});

以上がテキスト入力 API の基本的な利用方法です。

テキスト出力

テキスト出力は任意の文字列を 3D 空間上に表示できる機能です。
テキスト出力は、専用の TextView コンポーネントを用いると静的な表示テキストを設定できますが、スクリプト API を用いることで動的に指定できます。
表示される文字列は全ユーザーに同じ内容が同期されて表示されます。

テキスト出力を利用するには、任意の GameObject に TextView コンポーネントをアタッチして下さい。

テキストの内容やサイズ、色などを動的に変更する場合はスクリプト API を用いて下さい。
なお、 テキスト出力に関する各 API は任意の SubNode インスタンスからの実行となります。
API を実行するスクリプトから対象のサブノードが見つけられるようにしておく必要があることに注意して下さい。

setText(text: string): void
setTextAlignment(alignment: TextAlignment): void
setTextAnchor(anchor: TextAnchor): void
setTextColor(r: number, g: number, b: number, a: number): void
setTextSize(size: number): void

enum TextAlignment {
  Center,
  Left,
  Right,
}

enum TextAnchor {
  LowerCenter,
  LowerLeft,
  LowerRight,
  MiddleCenter,
  MiddleLeft,
  MiddleRight,
  UpperCenter,
  UpperLeft,
  UpperRight,
}
$.onInteract((_) => {
  const subnode = $.subNode("TextViewObject");
  subnode.setText("テキストを変更しました");
  subnode.setTextAlignment(TextAlignment.Center);
  subnode.setTextAnchor(TextAnchor.UpperCenter);
  subnode.setTextColor(1.0, 0.0, 0.5, 1.0);
  subnode.setTextSize(0.2);
});

テキスト出力とテキスト入力を組み合わせることで、ユーザーが入力した文字列を処理して表示させることもできます。

$.onInteract((playerHandle) => {
  playerHandle.requestTextInput("pizza", "入力した数字の数だけピザって言います");
});

$.onTextInput((text, meta, status) => {
  if (meta !== "pizza") {
    return;
  }
  if (status !== TextInputStatus.Success) {
    return;
  }

  const count = parseInt(text) || 0;
  const pizzas = new Array(count);
  pizzas.fill("ピザ");

  const output = pizzas.join("");

  const subnode = $.subNode("TextViewObject");
  subnode.setText(output);
});

メタデータ取得

ClusterScript ($)、 SubNode、 PlayerHandle のインスタンスから新たにいくつかのメタデータが取得できるようになります。

  • ClusterScript ($)

    • id

    • itemHandle

    • itemTemplateId

  • SubNode

    • name

  • PlayerHandle

    • userId

    • userDisplayName

特にClusterScript や SubNode のメタデータは、これまで煩雑だったサブノードやアイテムの識別が簡便になります。
また、PlayerHandle のメタデータは今回新規に取得できるようになった情報です。
userId も userDisplayName も、ユーザーが変更しない限りはワールド横断で同じ値を返します。
これを利用して、よりパーソナライズされたテキスト表現ができるようになったり、特定ユーザー用の処理ができるようになったりします。

詳しくはスクリプトリファレンスを参照して下さい。

ドキュメントの改善

cluster では日々、日本語圏以外のユーザーも増加しています。
今回のリリースからは、 cluster でのクリエイター活動が体験できないユーザーを減らしていくために、一部のリソースから英語翻訳対応を始めました。

github のリリースノート

github のリリースノートは、今回のリリース分から英語表記で統一するように変更しました。
オープンソースとしてグローバルから閲覧可能なプロジェクトは、より多くのデベロッパーが読める言語で情報を記載すべき、という判断に基づいた変更です。
日本語でのリリースノートは、当記事のような形でより詳細な情報と共にお届けします。

スクリプトリファレンス

Creator Kit 2.6.0 のリリースタイミングから 1週間ほど後になりますが、新たに英語翻訳されたページが追加されます。
今までどおり日本語でも閲覧可能です。

Creator Kit 利用者アンケートへのご協力をお願いします

Creator Kit を利用しているユーザーの要望や習熟度を定性的に知るために、Creator Kit にアンケートを追加しました。
Settings ウィンドウやコンテンツのアップロードの際に表示されるようになります。
ご回答にご協力いただけると助かります。

ご意見・ご感想お待ちしています

cluster は、みなさんが楽しくバーチャル空間で創造できるように様々な改善を行っています。
Discord ではみなさんの要望を投稿したり、クリエイターさん同士でお互いの創作活動を支え合える場所を設けていますので、ぜひご活用ください!

Discordサーバー: Creator Community のご案内
https://docs.cluster.mu/creatorkit/support/creator-community/