Boltで2Dアクションゲームのキャラクターを動かす【Unity+Bolt】

2020年6月10日

Unityで使うことができるビジュアルスクリプティングツールであるBoltを使って2D横スクロールのキャラクター移動に使う左右入力ジャンプボタンの入力を解説します。機能自体はシンプルなものになっています。ひとつずつ覚えていきましょう

今回の入力で使うゲーム画面とFlowGraph全体図

実際の動作する画面とグラフの全体図はこんな感じになっています。ブロックの上に乗って、左右で移動、ジャンプボタンでジャンプ。2段ジャンプは出来ないという構成です。グラフは大きく分けて5つ各機能については以下の表にまとめます。個別に解説を入れていきます。

グラフ説明
1.左右移動入力左右の入力と、それに対して補正をかけます
2.速度セット移動量と縦方向の速度を組み合わせてキャラにセット
3.キャラの向き移動方向に対してキャラの向きを変える
4.アニメーション速度を使って移動モーションの切り替え
5.ジャンプジャンプ入力を受けてジャンプ
接地しているときのみ飛べるようにする

説明は各グループごとにしていきます

1.左右移動入力

グループ1では左右の移動入力処理を実装します。入力された値はメンバー変数のMovementに保存されます。また、スピードの補正としてメンバー変数Speedと掛け合わされます。ここでのメンバー変数というのはあくまでイメージです。SpeedはObjectとなっていますが、Graphでも問題ありません。変数についてはまた別のところで説明いたしますね。

以上をプログラムっぽく書くと下記のようになります。グループをクラスのメンバー関数だと仮定するとこのような形になります。

	void MoveInput()
	{
		Movement = Input.GetAxis("Horizontal") * Speed;
	}

2.速度のセット

キャラクターの動きの制御は主にRigidbodyを使って操作します。キー入力での左右の速度の他に、落下中の速度を考慮する必要があるため、Rigidbodyに速度をセットする前に事前の縦方向の速度を取得する必要があります。Movementは1.のグループで変数を保存しています。接続順に気をつけることで、更新された値を使うことが出来ます。

こちらも関数と仮定してプログラム化してみましょう。1つずつやってるようで、プログラム化すると1行になるのが個人的にはシュールに感じますね。

	void SetVelocity()
	{
		gameObject.GetComponent<Rigidbody2D>().velocity = new Vector2(
			Movement,
			gameObject.GetComponent<Rigidbody2D>().velocity.y);
	}

3.キャラの向き

移動処理のみだとキャラクターの向きが対応出来ません。ここではLocalScaleを使って反転させます。コホあたりはちょっとごちゃごちゃしてきた感じがしますね。Movementを0と比較して向きを制御します。停止中(Movement=0)の時は例外として、向きを変更しないという処理も入れます。こうしておかないと停止するたびに毎回同じ向きを向いてしまうので入れる必要があります。

こっちもプログラム化するとわかりやすいですね。判定文から2つの矢印が出ていますが、つなぎ先の順番で、プログラム化するとこんな違いが出ます。ビジュアルスクリプティングは奥が深い。

	void CharacterFlip()
	{
		if( Movement == 0)
		{
		}
		else
		{
			gameObject.transform.localScale = new Vector3(
				Movement < 0 ? -1 : 1,
				1,
				1);
		}
	}

4.アニメーション

詳細は割愛しますが、アニメーションにはParameterにspeedというパラメータが用意されているとします。0より大きい値が入ると移動モーションに遷移して、小さくなるとまたIdle状態に戻る、というアニメーションを作成してください。(このあたりはUnityの普通の知識が必要になります)

アニメーションにわたす数字はマイナスだと都合が悪いので、絶対値としてスカラーを渡すようにします。

	void Animator()
	{
		gameObject.GetComponent<Animator>().SetFloat("speed", Mathf.Abs(Movement));
	}

5.ジャンプ

ここが一番ややこしいかもしれません。地面になるオブジェクトはレイヤーをFloorにしているのがポイントです。地面に設置しているかどうかの判定はCircleCastを使っています。パラメータがうまく設定できない場合は一度CircleCollidorを付けてみて、参考になりそうなパラメータの目処を付けてみると良いかもしれません。

注目したいのはOnButtonInputです。こちらはアクションの種類のイベントが走ったときだけ呼び出されます。ボタンが押された時、離された時、ホールド中などが選択できます。便利!Nameは今回はJumpとしてますが、こちらはProjectSettings>InputManagerの中にプリセットされているものが呼び出せます。

ソースコードはちょっとだけ擬似コード気味になってますが、だいたいこんな感じ。この関数はジャンプボタンを押し下げられたタイミングで呼ばれるようにイベント登録をする必要があります。

	void OnButtonInput_Down_Jump(bool _bInput)
	{
		if (_bInput)
		{
			RaycastHit2D hit = Physics2D.CircleCast(
				gameObject.transform.position,
				1.0f,
				new Vector2(0.0f, -1.0f),
				0.84f,
				LayerMask.NameToLayer("Floor"));
			if (hit.collider != null)
			{
				gameObject.GetComponent<Rigidbody2D>().AddForce(
					new Vector2(0, 8),
					ForceMode2D.Impulse);
			}
			else
			{
				Debug.Log("nothit");
			}
		}
	}

これで地面(Layer=Floor)に設置しているときのみジャンプができるようになります。CircleCastは別にLayerCastでも構いません。当たり判定は各自で勉強してくださいね!

基本的にはプログラムの知識が必要

シンプルなゲームなら十分使えそうな処理をご紹介しましたが、ご覧いただいたとおりどれもプログラムに変換することが出来ます。キー入力に関しては少しBoltの優秀さが出ましたが、それでも内容的にはプログラムになっています。

どのような当たり判定を使うかや、アニメーションとの連携処理などは、Unityの知識も必要になります。ビジュアルスクリプティングはたしかに便利なツールです。しかしそれらを使いこなすには基本的な知識が必要です。グラフを作って動いた際にはプログラムだとどうやって書くのかな?など想像すればコーディング力も上がると思いますので意識しながら使ってみてください。