👾

Unity用clusterスクリプトで追いかけっこ

2023/02/17に公開

(初出時、サンプルプロジェクトのzipがちゃんと載っていませんでした。。。修正しました)

今回はUnity用です。Constraint機能を併用し、乗りものに乗ったプレイヤーや「オーブ」を持ったプレイヤーを敵が追いかけてくるワールドのサンプルです。

Unityで開き、vins-jp/Oikake/Scenesフォルダにあるシーンを開いてください。

シーンOikakeSampleAは乗りものを追いかけてきます(当たり判定は乗りもの)。プレイヤーがボタンを押せばクリアです。

シーンOikakeSampleBはオーブを持ったプレイヤーを追いかけてきます。ランダムな5箇所のどこかにある、ゴールのハコにオーブを触れればクリアです。
当たり判定はオーブとプレイヤー両方にあります。またTerrain上を移動する関係で、$.setPositionではなくSet Velocity Character Item Gimmickを使って敵が動きます。

サンプルプロジェクト

zipファイルを解凍して、できた「OikakeSampleProject」フォルダをUnityHubなどから読み込んでください。
https://vins-jp.sakura.ne.jp/pack/OikakeSample.zip

モデル・マテリアル・スクリプト・音声などなど、改変はお好きにどうぞ~

サンプルをアップロードしたわーるど

サンプルシーン2つをアップロードしたワールドはこちら。
https://cluster.mu/w/c0e187cb-6158-45e8-aca4-4316e2d16005
https://cluster.mu/w/4cec88ac-e5d0-4cd3-9a8f-c493ee85120f

基本に自信がない人は

スクリプトの基本はこの記事を。

スクリプト(一部)

シーンOikakeSampleAで、乗りものを追いかけてくる敵のスクリプトです。
Constraint機能を使い、敵の子にある「DistanceObjE00」という空のオブジェクトの位置が、乗りものの子にある「DistanceObj00」の位置とピッタリ合うようになっています。

敵は自分の子である「DistanceObjE00」のほうに進めば、結果的に乗りものを追いかけることができるわけです。
また、上下移動(Y座標)を無視し、平面的に移動するようにしています。空中戦のワールドでない限り、このほうが便利なことが多いはずです。

改造のヒント

const distVec = distanceNode.getPosition();

の次に

if (distVec.lengthSq() > 25.0) {
	return;
}

と入れると、距離が5m以内でない限り動かなくなります。
(lengthSqは距離の2乗を計算します。このほうが平方根を使わないので距離の計算が速いのです)

スクリプト本文

const bodyNode = $.subNode("Body");
const distanceNode = $.subNode("DistanceObjE00");
const enemySpeed = 3.0;

const initProc = () => {
	$.state.initialized = true;
}


$.onUpdate((deltaTime) => {
	if (!$.state.initialized) {
		initProc();
	}
	
	if (!$.state.isStarted) {
		if ($.getStateCompat("this","OnStartFlag","boolean")) {
			$.state.isStarted = true;
			$.setStateCompat("this", "OnStartFlag", false);
		} else {
			return;
		}
	} else {
		if ($.getStateCompat("this","OnGameOverFlag","boolean")) {
			$.state.isStarted = false;
			$.setStateCompat("this", "OnGameOverFlag", false);

			return;
		}
	}
	const distVec = distanceNode.getPosition();
	const atanVal = Math.atan2(distVec.x, distVec.z)* 180 / Math.PI;
	const quat = new Quaternion().setFromEulerAngles(new Vector3(0, atanVal, 0));
	bodyNode.setRotation(quat);

	const pos = $.getPosition().add(new Vector3(0, 0, enemySpeed * deltaTime).applyQuaternion(quat));
	$.setPosition(pos);
}
);

$.onInteract(() => { 
	
});
//クリックしてOwnerになれるようにするためだけに付けている

Discussion