👻

【clusterスクリプト】パーツが動くクラフトアイテム

2024/07/14に公開

こんな感じで、パーツが動くクラフトアイテムです。

なおオリジナルのものを作るとき、クラフトアイテムは「メッシュが8種類まで」「マテリアルが2つまで」という制限があることにも注意しましょう。

クラフトアイテムのパッケージ

カプセル
https://vins-jp.sakura.ne.jp/pack/capsule.unitypackage
ウサギ
https://vins-jp.sakura.ne.jp/pack/usagi.unitypackage

まずはclusterのテンプレートワールドをダウンロード・MinimalSampleシーンなどを開きましょう
そしてダウンロードしたunitypackageをUnityにドラッグアンドドロップして追加してください。

この記事では、よりシンプルな「カプセル」のunitypackageのほうを使って説明していきます。

カプセルアイテムの構造



このように、Itemの子にbodyとhandRとhandLがあります。体と両手ですね。

スクリプトは?


ScriptableItemの「capsule_move」をクリックするとスクリプトの場所に飛べる。テキストエディタなどで閲覧しましょう
まず前半の基本構造から見ていきます。

const TICK_MAX = 2.0;

const body = $.subNode("body");
const handL = $.subNode("handL");
const handR = $.subNode("handR");

ここでは、「全体を何秒で繰り返すか(今回は2秒)」と、体のパーツ(subNode)を登録しています。

$.onStart(() => {
  $.state.tick = 0;
});

$.onUpdate((deltaTime) => {
  $.state.tick += deltaTime;
  if ($.state.tick > TICK_MAX) {
    $.state.tick -= TICK_MAX;
  }

  bodyProc();
  handLProc();
  handRProc();
});

さて、ここがメインパートですが、やっていることは

  • 毎フレーム $.state.tickを、経過時間(deltaTime)だけ増やしていく
  • 一定秒数(今回は2秒)過ぎたら最初に戻る
  • 各パーツの処理を呼び出す
    だけです。キモはbodyProcなどの各処理(と、本当はその先にも)にあるわけですね。

パーツの処理

体のパーツの処理を見てみます。

const bodyPos = [new Vector3(0, 0.5, 0), new Vector3(0, 0.65, 0), new Vector3(0, 0.45, 0)];
const bodyTick = [0, 0.5,1.5, TICK_MAX];
const bodyProc = () => {
  setPos(body, bodyPos, bodyTick);
};

なんだかよくわからないかもしれません。

  • bodyPosは、体の位置の移り変わりの内容
  • bodyTickは、何秒のタイミングで動きが切りかわるか
  • bodyProc、これが$.onUpdateから呼び出されているわけです。でも、やっていることはsetPosを呼び出すだけ(bodyは序盤で登録したsubNodeですね)
    ということになります。
    実は、メインの処理をしているのはもっとずっと後にあるsetPos関数です。ですが、その中身はだいぶややこしいので理解しなくてかまいません!

さて、もう少しデータを見ていきましょう。bodyPosは良く見るとVector3の2番目の数字、つまりY(上下)しか変わっていないことがわかります。0.5→0.65→0.45ですから、少しあがって、少し下がるわけですね。
つづけてbodyTickを見ると、「0.5秒、1.5秒」のタイミングで動きが切りかわることがわかります(TICK_MAXは序盤に登録した2.0秒)。

時間 処理
0秒~0.5秒 Yを0.5→0.65に
0.5秒~1.5秒 Yを0.65→0.45に
1.5秒~2.0秒 Yを0.45→0.5(元の数字に)

という処理であることがわかります。
基本はこれだけです!

回転のほうの処理

handL、左手のほうも見てみましょう(右手もほとんど同じ)。

const handLRot = [new Vector3(0, 0, 0), new Vector3(0, 0, 20), new Vector3(0, 0, -10)];
const handLTick = [0, 0.6,1.6,  TICK_MAX];
const handLProc = () => {
  setRot(handL, handLRot, handLTick);
};

今度はsetRotという関数を呼び出しています。回転させたいからですね。
handLRotは、Vector3の3番目の数字、つまりZが変わっています。パーツの配置によって色々変わってきますが、今回はZの値が「手を上下」させる回転に当たるのです。

時間 処理
0秒~0.6秒 回転Zを0→20に
0.6秒~1.6秒 回転Zを20→-10に
1.6秒~2.0秒 回転Zを-10→0(元の数字に)

なお、ここでの回転は0~360度で表現される数字です。算数とか数学で習ってきた、一番メジャーな角度の表現方法ですね。

他の部分は?

別に理解しなくてもいいです!
setPosとsetRotを使い、そこに適切なデータをあげるだけで問題ありません。

ウサギのほうはスクリプトがもっとフクザツ(パーツが多いので……)ですが、結局やっていることは全然変わりません。

位置を動かす時ただ一定のペースで動かすのではなく滑らかにする 、特に書かなくても最後は位置や回転を初期値に戻す、などの処理も加えていますが、そういう部分を理解するのはもっと先でかまいません。

まずは用意された関数を使って改変することに慣れてください。それだけでもかなり大変だと思うので……

Discussion