🐶
cluster アイテム持ったらプレイヤーについてくるサンプル [ベータ機能]
アイテム持ったら プレイヤーについてくる サンプル
サンプルワールド
アイテム持ったらプレイヤーについてくる サンプル
使うコンポーネント や メソッド
Creator Kit
ClusterScript
ItemHandle
ベータを有効にする
addForceAt (Beta) を利用するので、ベータ機能を有効にする必要があります。
Unity - > cluster -> 設定 を開いて ベータ機能を有効にするのチェックを入れる
プレイヤーに付いてくるアイテム
- GameObject に Movable Item と Scriptable Item をつける
- Unity の Project ウインドウ で 適当なフォルダを作成する
- Project ウインドウ -> Code -> cluster -> ClusterScript で
Partner.js
ファイルを作成する - 下記の内容をファイル内に書く
- 1で作成した GameObject の
Scriptable Item
の Source Code Asset に設定する
Partner.js
/** プレイヤーを追いかける スクリプト
*
* 概要
* プレイヤーが特定のアイテムを持っている時だけ、プレイヤーを追いかける
*
* 1. プレイヤーが特定のアイテムを持った場合に itemHandle.send でメッセージが送られてくる
* 2. $.onReceive で受信する
* 4. プレイヤーを追いかける
* 5. プレイヤーがアイテムを落とした場合に、モードを変更して追いかけるのをやめる
* 6. ターゲット設定している プレイヤーを null にして解除する
*/
const force = 30;
const maxDistance = 10;
const minDistance = 1;
const rad2deg = (rad) => rad * 180 / Math.PI;
const MODE = {
INITIAL:0,
INITIALIZED:1,
FOLLOW:2,
UNFOLLOW:3,
};
const RECEIVE_TYPE = {
FOLLOW: 'follow',
UNFOLLOW: 'unfollow',
}
const setMode = (mode) => {
$.state.mode = mode;
switch(mode) {
case MODE.INITIAL:
initial();
break;
case MODE.INITIALIZED:
// 初期化完了
break;
case MODE.FOLLOW:
// プレイヤーを追いかける
follow();
break;
case MODE.UNFOLLOW:
// 追いかけるのをやめる
unfollow();
break;
}
}
const initial = () => {
$.log('onStart');
$.state.targetPlayerIdfc = null;
setMode(MODE.INITIALIZED);
}
// プレイヤーを追いかける
const follow = () => {
$.log('follow');
// 近くのプレイヤーを探す
$.state.targetPlayerIdfc = $.state.arg.idfc;
}
// プレイヤーを追いかけるのをやめる
const unfollow = () => {
$.log('unfollow');
$.state.targetPlayerIdfc = null;
}
// 近くの対象プレイヤーを探す
const findPlayer = () => {
if ($.state.targetPlayerIdfc == null) return null;
const position = $.getPosition();
const players = $.getPlayersNear(position, maxDistance);
let targetPlayer = null;
players.forEach(player => {
if(player.idfc === $.state.targetPlayerIdfc) {
targetPlayer = player;
}
});
// ログアウトしている場合は null を返す
if (targetPlayer.exists() == false) return null;
return targetPlayer;
}
// 近くのプレイヤーを追いかける
const followTargetPlayer = (deltaTime) => {
const position = $.getPosition();
// 近くのプレイヤーを探す
const player = findPlayer();
if (player == null) {
// プレイヤーが見つからない場合は追いかけない
return;
}
// プレイヤーがいる方向の角度を計算してY軸回転
const direction = player.getPosition().clone().sub(position);
const angle = rad2deg(Math.atan2(direction.x, direction.z));
const rotation = new Quaternion().setFromEulerAngles(new Vector3(0, angle, 0));
$.setRotation(rotation);
// プレイヤーと一定より離れているときに、正面方向に押し出す力を加えて前進
if (direction.length() > minDistance) {
const v = new Vector3(0, 0, force).applyQuaternion(rotation);
$.addForceAt(v, position);
}
}
// 停止させる
const stop = () => {
const position = $.getPosition();
$.setPosition(position);
}
$.onStart(() => {
$.log('onStart');
setMode(MODE.INITIAL);
});
$.onPhysicsUpdate(deltaTime => {
switch($.state.mode) {
case MODE.FOLLOW:
// プレイヤーを追いかける
followTargetPlayer(deltaTime);
break;
case MODE.UNFOLLOW:
// 追いかけるのをやめる
stop();
break;
}
});
// プレイヤーが特定のアイテムを 持つ,落とした 場合にメッセージが送られてくる
$.onReceive((messageType, arg, sender) => {
// $.log('onReceive');
// $.log(`messageType: ${messageType}`);
// $.log(`arg: ${arg.idfc}`);
// $.log(`sender: ${sender}`);
$.state.arg = arg;
switch(messageType) {
case RECEIVE_TYPE.FOLLOW:
// 持った場合
setMode(MODE.FOLLOW);
break;
case RECEIVE_TYPE.UNFOLLOW:
// 落とした場合
setMode(MODE.UNFOLLOW);
break;
}
});
プレイヤーが持つ アイテム
- 持つと 追従, 落とす(離す) と 追従をやめる アイテム
- Unity の Project ウインドウ で 適当なフォルダを作成する
- Project ウインドウ -> Code -> cluster -> ClusterScript で
GrabItem.js
ファイルを作成する - 下記の内容をファイル内に書く
- 1で作成した GameObject の
Scriptable Item
の Source Code Asset に設定する
GrabItem.js
/** プレイヤーが持つと パートナーがついてくるアイテム
*
*/
const maxDistance = 10;
const MODE = {
INITIAL:0,
INITIALIZED:1,
GRAB:2,
DROP:3,
};
const RECEIVE_TYPE = {
FOLLOW: 'follow',
UNFOLLOW: 'unfollow',
}
const initial = () => {
$.log('onStart');
$.state.targetPlayer = null;
setMode(MODE.INITIALIZED);
};
// 持った
const grab = () => {
$.log('grab');
const targetPlayer = $.state.targetPlayer;
// 近くのアイムに送信する
sendItemsNear(RECEIVE_TYPE.FOLLOW, targetPlayer.idfc);
};
// 落とした
const drop = () => {
$.log('drop');
const targetPlayer = $.state.targetPlayer;
// 近くのアイムに送信する
sendItemsNear(RECEIVE_TYPE.UNFOLLOW, targetPlayer.idfc);
};
// 近くのアイムに idfc を送信する
const sendItemsNear = (type, idfc) => {
const position = $.getPosition();
const items = $.getItemsNear(position, maxDistance);
const arg = {idfc: idfc};
items.forEach(item => {
item.send(type, arg);
});
};
const setMode = (mode) => {
$.state.mode = mode;
switch(mode) {
case MODE.INITIAL:
initial();
break;
case MODE.INITIALIZED:
// 初期化完了
break;
case MODE.GRAB:
// 持った
grab();
break;
case MODE.DROP:
// 落とした
drop();
break;
}
};
$.onStart(() => {
$.log('onStart');
setMode(MODE.INITIAL);
});
// 持ったり, 落としたり
$.onGrab((isGrab, isLeftHand, player) => {
$.state.targetPlayer = player;
if(isGrab) {
setMode(MODE.GRAB);
} else {
setMode(MODE.DROP);
}
});
Discussion