本記事はCluster Creator Kitの「ベータ機能」を利用した解説になります。
ベータ機能では正式リリース前の機能を使うことができます。正式リリース前のため、不安定な挙動をしたり将来的に挙動が変わる可能性があります。
利用にはCluster Creator Kitでベータ機能を設定した状態でアップロードを行う必要があります。ワールドクラフトで利用する場合は、ワールドクラフトのワールドを新規作成する際にベータ機能の設定を行う必要があります。設定方法はこちらをご覧ください。
今回は「異なるアイテム同士がメッセージをやりとりできる」機能を使ったアイテムの作成方法を紹介します。
この機能を使って、「当てるとダメージを与えるアイテム」と「ダメージを受けると消えるアイテム」をつくります。

サンプルコード
攻撃するアイテム
まず、攻撃側のアイテム(武器)をつくります。
空のGameObjectを作成し、「Grabbable Item」「Scriptable Item」コンポーネントを設定してください。子オブジェクトに3Dモデルとコライダーも配置しましょう。
続いて当たり判定用のコライダーを設定します。
攻撃の判定をつけたい部分に合わせてコライダーを追加し、コライダーのGameObjectに「Overlap Detector Shape」コンポーネントを追加します。
Overlap Detector Shapeを含むShape系コンポーネントは今回のアップデートで新たに追加されたコンポーネントで、そのコライダーがどういった種類のものであるかを示します。
Overlap Detector Shapeが設定されたコライダーはIs Triggerとして振る舞い、後述の「$.getOverlaps()」の判定に利用されます。

最後に、Scriptable Itemコンポーネントに以下のスクリプトを設定してください。
$.onUpdate(deltaTime => {
// 初期化
if (!$.state.initialized) {
$.state.initialized = true;
$.state.overlapItems = [];
}
// 前のフレームで接触していたアイテムIDの一覧
let previousOverlapItems = $.state.overlapItems;
// このフレームで接触しているアイテムIDの一覧
let currentOverlapItems = [];
// 接触しているオブジェクトをすべて取得
let overlaps = $.getOverlaps();
overlaps.forEach(overlap => {
// 接触しているオブジェクトがアイテムであるかどうかを確認
let itemHandle = overlap.object.itemHandle;
if (itemHandle == null) return;
// 現在接触しているアイテムの一覧に追加
currentOverlapItems.push(itemHandle.id);
// 前のフレームで接触していたアイテムは除外
// メッセージの送信には頻度制限があるためその対策、また接触し続けた場合にダメージが入り続けることを防止
if (previousOverlapItems.includes(itemHandle.id)) return;
// メッセージを送信
itemHandle.send("damage", 10);
});
// 接触しているアイテムの一覧を更新
$.state.overlapItems = currentOverlapItems;
});
攻撃を受けるアイテム
上の武器アイテムから一定以上のダメージを受けると消えるアイテムをつくります。
空のGameObjectにScriptable Itemコンポーネントを追加し、子オブジェクトにモデルやコライダーを配置します。
アイテムが用意できたら、Scriptable Itemに以下のスクリプトを設定します。
$.onReceive((requestName, arg, sender) => {
// 初期化
if (!$.state.initialized) {
$.state.initialized = true;
$.state.hp = 30;
}
// 特定のrequestNameのときだけ処理
if (requestName == "damage") {
// 引数の値の分だけHPを減らす
let hp = $.state.hp - arg;
// HPが0以下になると破壊
if (hp <= 0) {
$.destroy();
}
$.state.hp = hp;
}
});
それぞれのアイテムが設定できたら、ベータ機能を有効にしたアイテムとしてアップロードし、確認してみましょう。
今回のサンプルは現時点ではUnityワールドでは正しく動作しないことがあります(後述)。クラフトアイテムとしてアップロード後、ワールドクラフト上で設置して確認してみてください。
サンプルコードの解説
新しい機能を利用している部分を中心に、サンプルコードを解説します。
let overlaps = $.getOverlaps();
$.getOverlaps()
で、アイテムと重なっている(接触している)すべてのオブジェクトを配列として取得できます。
let itemHandle = overlap.object.itemHandle;
このoverlap
は$.getOverlaps()
で取得した配列の要素で、アイテムと重なっているオブジェクトを示します。
重なっているオブジェクトがアイテムであった場合、overlap.object.itemHandle
でそのアイテムのハンドルを取得できます。対象がアイテムでない場合はnullになります。
currentOverlapItems.push(itemHandle.id);
itemHandle.id
でそのアイテムを一意に識別するIDが取得できます。接触しているアイテムのIDを$.state.overlapItems
に保存し、接触し続けているかどうかの判定に利用しています。
itemHandle.send("damage", 10);
対象のアイテムにメッセージを送信します。
メッセージの種類を示すための文字列と、メッセージの内容である引数を渡すことができます。
$.onReceive((requestName, arg, sender) => {
メッセージを受け取った際に呼び出される処理を記述します。
requestNameにはメッセージの種類を示すための文字列が、argには引数が格納されます。senderにメッセージの送信元アイテムのItemHandleが格納されているため、結果などを返信することもできます。
$.destroy();
$.destroy()
を呼び出すと、そのアイテムを消滅させることができます。
現時点ではUnityワールドで最初から置かれているアイテムでは動作せず、クラフトアイテムとして設置した場合か、Create Item Gimmickや$.createItem()
メソッドなどによって動的に生成されたアイテムでのみ有効です。
複雑なメッセージを送る
先ほどはメッセージの引数として数値だけを設定しましたが、この引数にはハッシュ形式で複雑な内容を渡すこともできます。
スクリプトを以下のように変えてみましょう。
hp = $.state.hp - arg;
↓
let damage = arg.value;
if (arg.type == "fire") damage *= 2;
let hp = $.state.hp - damage;
ダメージ量に加えて、属性の情報も付加するようにしました。特定の属性だとダメージが2倍になります。
typeの値を「fire」から「water」「electric」などに置き換えたアイテムをいくつか用意して、試してみましょう。
今回実装されたメッセージ機能を使うと、他の人がアップロードしたアイテム同士であっても、requestNameや引数の形式が適切であれば互いにメッセージをやり取りすることができます。
↓