![見出し画像](https://assets.st-note.com/production/uploads/images/101519227/rectangle_large_type_2_23036d4baa7e75e2cad697ac6dd36a42.png?width=800)
【ClusterScript】クリエイターズガイドのスクリプトアイテムを作ってみた【エレベーター編】
clusterクリエイターズガイドに記載されているスクリプトアイテムをコードのコピペで作れなかったので自分で作り直すことにしました。
この記事で配布するサンプルアイテムは自由にご利用ください。
▼ 元記事
①オブジェクトを作る
まず、クリエイターズガイド記載のヒエラルキー構成では作成できなかったので別途こちらで用意しました。
こちらからUnityプロジェクトをダウンロードできます。
ヒエラルキー構成をElevator>Container>Door_R, Door_L としました。
※クリエイターズガイドの「Cage」「Collider」は動きのない外枠のため、今回は削除しています。
![](https://assets.st-note.com/img/1679923568034-OblEDdMaVL.png?width=800)
Elevator:Item(Script)のSizeを床タイプ(2,0,2)としました。
Container:上下する床のオブジェクトです。
Door_R, Door_L:ドアです。停止中は開き、移動中は閉じます。
②コード
サンプルコードから以下の2か所を書き換えています。
// エレベーターの移動先の高さや、各部品のサイズを定義する
// ドアの位置を更新する
※解説のためコメントを挿入しています。
// 3つの子オブジェクトを取得する
const container = $.subNode("Container");
const doorLeft = $.subNode("Door_L");
const doorRight = $.subNode("Door_R");
// 待機時間、移動時間、周期を定義する
const waitTimeSec = 10;
const transitTimeSec = 10;
const period = (waitTimeSec + transitTimeSec) * 2;
// エレベーターの移動先の高さや、各部品のサイズを定義する
const targetHeight = 4;
const offsetHeight = 0.025;
const doorWidth_X = 0.25;
const doorWidth_Y = 19.5;
const doorWidth_Z = 0.5;
// イージング関数を定義する
const easeInOutQuad = (t) => {
return t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
};
// 上昇時のエレベーターの位置を計算する関数を定義する
const upwardsCagePosYRatio = (time) => {
if (time <= waitTimeSec) {
return 0;
} else {
return easeInOutQuad((time - waitTimeSec) / transitTimeSec);
}
};
// エレベーターの位置を計算する関数を定義する
const cagePosYRatio = (time) => {
time = time % period;
if (time < period / 2) {
return upwardsCagePosYRatio(time);
} else {
return 1 - upwardsCagePosYRatio(time - period / 2);
}
};
// ドアの位置を計算する関数を定義する
const doorPosXRatio = (time) => {
time = time % (period / 2);
if (time <= waitTimeSec) {
return 1;
} else {
return 0;
}
};
// フレーム毎に呼び出されるアップデート関数を定義する
$.onUpdate(deltaTime => {
// 経過時間を計算する
let time = $.state.time ?? 0;
time += deltaTime;
$.state.time = time;
// エレベーターの位置を更新する
container.setPosition(
new Vector3(
0,
cagePosYRatio(time) * targetHeight + offsetHeight,
0));
// ドアの位置を更新する
doorLeft.setPosition(
new Vector3(doorPosXRatio(time) * doorWidth_X * 2 + doorWidth_X , doorWidth_Y, doorWidth_Z));
doorRight.setPosition(
new Vector3(doorPosXRatio(time) * -doorWidth_X * 2 - doorWidth_X , doorWidth_Y, doorWidth_Z));
});
※補足
「エレベーターの移動先の高さや、各部品のサイズを定義する」の箇所ではオブジェクトに合わせて数値を変更してください。
この数値をもとに開閉時のドアの位置を決定しています。
// エレベーターの移動先の高さや、各部品のサイズを定義する
// Containerの到達地点の高さ
const targetHeight = 4;
// Containerの初期高さ
const offsetHeight = 0.025;
// ドアの初期位置(X,Y,Z)
const doorWidth_X = 0.25;
const doorWidth_Y = 19.5;
const doorWidth_Z = 0.5;
ドアが綺麗に開閉しない場合は最後の行の「 // ドアの位置を更新する」をチェックし、位置を計算してください。
※「doorPosXRatio(time)」は開くと1,閉じると0となります。
解説
最初に、エレベーターの部品を取得します。containerはエレベーターの実際の移動を担当する部品、doorLeftとdoorRightは自動ドアを制御する部品です。
次に、エレベーターの移動に必要なパラメータを設定しています。waitTimeSecは停止する時間、transitTimeSecは移動にかかる時間を表します。また、targetHeightはエレベーターが到達する目的の高さ、offsetHeightはエレベーターの位置を微調整するためのオフセットです。doorWidthは自動ドアの幅を表します。
easeInOutQuadはイージング関数で、エレベーターの上下運動の滑らかさを調整するために使われます。upwardsCagePosYRatioは、上向き運動の際のcontainerの位置を計算する関数で、cagePosYRatioはエレベーターの現在位置に応じてcontainerの高さを計算する関数です。doorPosXRatioは、自動ドアの位置を計算する関数です。
最後に、$.onUpdate()メソッドで、エレベーターの移動とドアの開閉を制御します。deltaTimeは前回のonUpdate()呼び出しからの経過時間です。timeはエレベーターの現在の時間を表します。containerと自動ドアの位置は、現在の時間に応じて計算されます。時間の経過は$.state.timeに保存され、次回のonUpdate()呼び出し時に再利用されます。
また、このスクリプトでは以下のような関数が定義されています。easeInOutQuad: イージング関数。引数の値に応じて0から1の範囲で値を返します。ここでは二次曲線のイージング関数が使用されています。
upwardsCagePosYRatio: コンテナが上昇中のときの高さの割合を返します。
cagePosYRatio: コンテナの高さの割合を返します。一定時間上昇した後、一定時間下降し、元の位置に戻るという動きを表現しています。
doorPosXRatio: ドアが開閉しているときにドアの位置の割合を返します。
また、以下の定数や変数が使われています。waitTimeSec:エレベーターが停止している時間(秒)
transitTimeSec:エレベーターが上昇・下降する時間(秒)
period:エレベーターの一周にかかる時間(秒)
targetHeight:エレベーターの到達目標高さ
offsetHeight:エレベーターが止まっているときの高さのオフセット
doorWidth:ドアの幅
onUpdate関数では、現在の時間を取得し、cagePosYRatio関数やdoorPosXRatio関数を使ってコンテナとドアの位置を計算して、それぞれのオブジェクトに設定しています。時間は、stateオブジェクトのtimeプロパティを通じて保存されており、deltaTimeを加算することで更新されています。
関連記事
ドア編はコチラ↓
この記事が気に入ったらサポートをしてみませんか?