
4. ワールドクラフト・$.log()を使った動作確認, ベクトルを使おう, 位置・回転を操ろう
さて, 今回はCluter Javascriptでのベクトルの扱いについて紹介する.
だがその前に, これまでの記事を読む中でみなさんこう思ったことはないだろうか?
1回1回アップロードして動作確認するの面倒…
準備編でCluster JavascriptはUnityのプレビュー上で動作しないため都度アップロードする必要があると言った.
だが実を言えば, 全てのスクリプトがそうであるわけではない.
ワールドクラフト上でもスクリプトの入力は可能で, しかも即座に実行することが可能なのだ.
ワールドクラフトで動作確認をしよう
ScriptableItemをアップロード, スクリプトエディタを起動する
ワールドクラフトでスクリプトを入力するためには,
ScriptableItemをつけたアイテムをアップロードして,
スクリプトエディタをClusterアプリ上でOnにする必要がある.
こちらの記事を参考にしてほしい.
※この後onInteractトリガーを使うため,
アップロードするアイテムにはMovableItemを付与しておいてほしい.
(ちなみに, MacはF12と書いてあるキーは音量操作ボタンだが,
fnキーと同時に押すことでスクリプトエディタを起動できる)
うまくいけば, 以下のようにスクリプトを入力できるはずだ.

$.log()を使う
さて, ワールドクラフトでスクリプトを入力できるようになったが,
ワールドクラフトではSetTextGimmickが使えないため,
スクリプト内の情報は別のやり方で出力する必要がある.
$.log()だ.

$.onInteract(() => {
$.log('a')
});

その場でコピペ入力して, その場で実行できるため, 非常に楽である.
この後の機能の動作確認も$.log()を使ってみよう.
ベクトルを使おう
ベクトルの宣言
さて, ベクトルの説明に入る.
まずは変数を宣言してVector3を代入しよう.

$.onInteract(() => {
let a = new Vector3(1,2,3);
$.log(a);
});

また, 以下の形でVector3の中の成分も出力できる.

$.onInteract(() => {
let a = new Vector3(1,2,3);
let a_x = a.x;
let a_y = a.y;
let a_z = a.z;
$.log(a_x);
$.log(a_y);
$.log(a_z);
});
簡単な演算
Vector3を用意できたら, 次は計算だ.
数値については+や-を使った馴染みやすい計算ができたが,
Vector3はちょっと違う形になる.

出力先 = 引数1.clone().add(引数2) (⇄ 出力先 = 引数1 + 引数2)
という形だ.
(このadd関数なのだが, aつまり引数1に影響を与えることがあるらしい.
clone()を使ってaを複製したものを引数にしている.)
他の演算も同様の形である.

c = a.clone().add(b);
c = a.clone().sub(b);
c = a.clone().multiply(b);
c = a.clone().divide(b);
c = a.clone().length();
また, Vector3同士の演算だけでなく, 数値を用いた演算もできる.

$.onInteract(() => {
let a = new Vector3(1, 2, 3);
let b = 4;
let c = a.clone().addScalar(b); //c = new Vector3(a.x+b, a.y+b, a.z+b);
$.log(c)
});
他の演算

c = a.clone().addScalar(b);
c = a.clone().subScalar(b);
c = a.clone().multiplyScalar(b);
c = a.clone().divideScalar(b);
ちなみに, Vector3の成分を出力したものに演算を加えても,
元のVector3に影響は与えられないので注意しよう.


位置を操ろう
さて, ここまででClusterJavascriptにおけるVector3の扱いについて説明した.
次に, このVector3を用いてアイテムの位置を操作する方法を説明する.
だがその前にGrabbableItemを付与したアイテムを用意して欲しい.
getPosition()
さて, GrabbableItemを付与したアイテムが用意できたら,
その位置を取得してみよう.
getPosition()だ.

$.onGrab(isGrab => {
$.log($.getPosition())
});

getPosition()で取得したVector3に演算を加えることもできる.

$.onGrab(isGrab => {
let Position = $.getPosition()
let a = Position.clone().add(new Vector3(0,2,0));
$.log(a);
});

setPosition()
アイテムの座標をVector3の形で取得するだけでなく,
アイテムをVector3の形で表した座標に移動させることもできる.
setPosition()だ.

setPosition()関数は掴んでいるアイテムには適用されないため必須ではない
$.onGrab(isGrab => {
if(isGrab==false){
let a = new Vector3(1, 2.5, 13.5);
$.setPosition(a);
}
});

getPosition()と組み合わせれば,
手放したとき掴む直前にあった場所に戻すギミックを作れる.

→放したときstate変数aの位置に移動
$.onGrab(isGrab => {
if ($.state.a == null) { $.state.a = new Vector3(0,0,0); }
if(isGrab==true){
$.state.a = $.getPosition();
}else{
$.setPosition($.state.a);
}
});

回転を操ろう
さて, 位置の操作ができるようになったところで,
同じように回転の操作をしよう…と言いたいところだが,
ClusterJavascriptでの回転の操作は位置の操作とやや勝手が異なる.
位置と同じようにgetRotation(), setRotation()が用意されているのだが
これらはVector3ではなくQuaternionという4次元ベクトルを使う.
回転の表現方法
まず, 回転とはベクトルでどうやって表現されるのかについて説明する.
オイラー角 : 3次元ベクトルによる回転の表現

横, 上, 正面方向のx, y, z軸まわりにどれだけ回転するかを
3次元ベクトルで表現する方法だ.
CCKに慣れている人ならこちらの表現に馴染みがあるだろう.
Quaternion : 回転軸の方向+回転量による表現

3次元ベクトルで回転軸を1つ定義し, そのまわりにどれだけ回転しているかで回転を表現する方法だ.
実際のQuaternionの各要素に入る数値は計算の都合上、直感的ではないものとなっている. そのため, Quaternionに直接数値を入れることはせず, 以下に紹介するよう関数を挟んだやり方を使うことをおすすめする.
※参考
getRotation().createEulerAngles()

$.onGrab(isGrab => {
$.log($.getRotation().createEulerAngles())
});

アイテムの回転をオイラー角で表現したVector3を取得する.
getRotation()で取得されたQuaternion表現の回転を
createEulerAngles()でオイラー角表現に変換するという構造だ.
setRotation(new Quaternion().setFromEulerAngles())

$.onGrab(isGrab => {
if(isGrab==false){
let a = new Vector3(45, 45, 45);
$.setRotation(new Quaternion().setFromEulerAngles(a));
}
});

アイテムをVector3でオイラー角表現した回転で設置する.
Vector3をsetFromEulerAngles()で変換して新しいQuaternionを作り,
その回転にsetRotation()で設置するという構造だ.
setRotation(new Quaternion().setFromAxisAngle( , ))

$.onGrab(isGrab => {
if(isGrab==false){
let a = new Vector3(1, 1, 1);
let b = 45
$.setRotation(new Quaternion().setFromAxisAngle(a, b));
}
});

アイテムをVector3で指定した軸と回転量で表現した回転で設置する.
先述したQuaternion表現の回転を直感的に扱えるようにした関数だ.
ベクトルを回転させる
applyQuaternion()

$.onGrab(isGrab => {
if(isGrab==false){
let a = new Vector3(0, 0, 1);
a = a.applyQuaternion($.getRotation());
$.log(a)
}
});

次回へ
今回はワールドクラフトでの動作確認, Vector3の扱い, 位置・回転の操作について説明した.
位置や回転の自由な操作はスクリプト対応に伴って追加された新しいギミックで, 特にワールドクラフトにおいてはワールドの自由度を大きく広げる存在だ.
次回はアイテムの一部, 子だけ動作させるための定数, subNodeについて説明する. こちらだ.
待つのだ.
余談
noteにも投げ銭機能があるらしい. 100円からできるみたい.
下の「気に入ったらサポート」から支援できます.
非常に嬉しく, また執筆の助けになりますのでよろしくお願いします!