はじめに
この記事ではUnity 2021から標準パッケージになったVisual Scriptingで、Chromeの恐竜(chrome://dino/)ライクなシンプルな横スクロールゲームを作成する方法を解説します。
この記事の対象としては、以下のような方を想定しています。
- Unityを少しでも触ったことがある方
- Visual Scriptingに興味がある方
環境
Unity 2021.2.6f1
Visual Scriptingとは
Visual Scriptingとは、コーディングの代わりにグラフを作成してプログラムを記述可能なシステムです。
これには以下のような利点があります
- 「なんとなく」で使えるため非エンジニアでも触りやすい
- C#で記述したプログラムと共存可能
- Play中にも処理を変更できるためプロトタイプ作成などにおいて素早くトライアンドエラーをまわせる
- 実行中の処理が可視化されるため、簡単な処理ならデバッグがしやすい
(↓実行中のグラフで、処理の流れが可視化されている&線上にそのフレームの値が表示されている)
この機能はUnity 2020まではBoltと呼称されていたパッケージでしたが、Unity2021から名前を変え標準パッケージとなりました。
そのため、Unity2021をインストールするだけで利用が可能です。
作るもの
今回の記事では、Visual Scriptingを使用して↓のような簡略版恐竜ゲームを作ります。
(白丸が恐竜、黄色長方形がサボテンだと読み替えてください。)
必要な機能
これを作る上で、まず最低限必要な機能を書き出してみます。
- 障害物が左に動く
- ボタン押下に応じてプレイヤーがジャンプ
- 数秒おきに障害物を生成
- スコア表示
- 死亡処理(スコアなどの停止)
なんとなく似たゲームができそうですね。
ただ、全て実装すると記事が長くなりすぎるので、今回は基礎として1と2を作るところを目標にします。
では、作っていきましょう。
実践
プロジェクトの作成
まずはプロジェクトの作成です。
- Unity Hubの新規作成から
Unity 2021.2.6f1
を選択 - テンプレートに
2D
を選択して作成
を選択
GameObjectの配置
ここで、先にGameObjectをある程度まとめて配置してしまいましょう。
今回のゲームの登場人物はプレイヤー、床、障害物の3つです。
今回は面倒なので工数削減のため、プレイヤーは白い丸、床は白い長方形、障害物は黄色の長方形で代用します。
プレイヤーの配置
- Hierarchyで右クリック -> 2D Object -> Sprites -> Circle をクリック
- GameObjectの名前をPlayerに変更
- Add ComponentでCircle Collider 2Dを選択
- Add ComponentでRigid Body 2Dを選択
床の配置
- Hierarchyで右クリック -> 2D Object -> Sprites -> Square をクリック
- GameObjectの名前をFloorに変更
- Add ComponentでBox Collider 2Dを選択
障害物の配置
- Hierarchyで右クリック -> 2D Object -> Sprites -> Square をクリック
- GameObjectの名前をTreeに変更
- Add ComponentでBox Collider 2Dを選択
- Spriteの色を黄色に変更(任意)
障害物の動きの作成
今回のゲームでは右から左に障害物が線形に移動していきます。
この動きをVisual Scriptingを用いて作成してみます。
コンポーネントのアタッチ
まず、TreeにAdd ComponentでVisual Scripting->Script Machineを選択してください。
(Boltを使ったことがある方はとりあえずScript Machine = Flow Machineだと思って大丈夫です。)
すると以下のような2つのコンポーネントがアタッチされます。
ここで、Script MachineコンポーネントのSourceという項の選択により、Script MachineコンポーネントはGraph
とEmbed
どちらかのモードを選択できます。
それぞれの違いは以下の通りです。
- Graph : グラフをファイルとして保存する。再利用可。
- Embed : グラフがコンポーネントに埋め込まれる。(基本的には)再利用不可。コンポーネントをRemoveするとグラフも消える。
基本的にはGraphを選択して一つ一つ保存した方が良いと思われますが、今回は説明の簡略化のためEmbedを使用します。
SourceにEmbedを選択するとTitleを付けられるようになるので、今回の機能としてTreeMovement
と入力してください。
ちなみに、Convertを選択することでEmbedで作成したグラフを後からファイルに書き出すことも可能です。
(詳しくはこちらを参照してください)
グラフの作成
次に、Script MachineコンポーネントのEdit GraphをクリックしてScript Graphウィンドウを開きましょう。
最初に開いた時はウィンドウが小さく肝心のグラフが見えない場合があるので、その時は横幅を広げましょう。
このウィンドウの見方をざっくり解説すると以下のような感じです。
- 左上 : Graph Inspector
- 選択したグラフの詳細を表示
- 左下 : Blackboard
- 変数の管理
- 右 : グラフエディタ
- 実際に処理を記述する場所
最初は、基本右側を使うんだなくらいの認識で大丈夫です。
ノードの配置
では、実際にグラフを作成していきましょう。
まず、グラフ上で右クリックをしましょう。すると、ノードの作成ポップアップが開くと思います。
ここでいうノードとは、処理のひとかたまりだと考えて下さい。(C#でいう関数のようなもの)
↓ ノードの一例: Rigidbody.AddForce()
今回は左に移動してほしい、つまり障害物のポジションを移動させたいので、translate
と入力し、Transform: Translate(X,Y,Z)
を選択してください。(C#でいうtransform.Translate()
と考えて大丈夫です)
すると以下のようになると思います。
この状態ではノードが何にもつながっていないため、処理が走りません。
次はこのノードを線でつないで処理を記述していきます。
処理の記述
ここでやりたいことは右から左へ位置を移動させる、つまり「毎フレーム -x 方向にポジションを移動させる」ことです。
毎フレーム行う処理を記述する場合、On Update
イベントを用います。(C#でいうUpdate()です。)
今回は、On Update
イベントからTranslate
ノードを繋ぎます。
こうすることで毎フレームTranslate
ノードの処理が呼ばれることになります。
また、左方向に移動させたいのでX
にマイナスの数値を入力しましょう。
この状態でPlayすれば、Treeというオブジェクトがひとまず左に動いてくれるはずです。
(上記の状態だとフレームレートによってTreeが動く速度が変わってしまうため、最終的には以下のようにdeltaTimeを乗算しましょう。)
プレイヤーのジャンプ
障害物の動きが出来たところで、キーの押下に応じてプレイヤーがジャンプする動きを実装します。
ここで、プレイヤーは接地状態、ジャンプ状態という2つの状態を行き来する、とも考えられます。
それぞれの状態は以下の通りです
- 接地状態 : キーを押下でジャンプ状態へ移行する。
- ジャンプ中 : この状態に入った瞬間上方向に飛び上がる。床に触れた時接地状態へ移行する。
この状態遷移を簡単に実現できる機能がState Machineです。
今回はこのState Machineを用いてジャンプを実装します。
コンポーネントのアタッチ
ではさっそくState Machineを作成しましょう。
Playerオブジェクトを選択して、Add ComponentからState Machineを選択してください。
ここでもSourceにGraphかEmbedを選べますが、今回は例によってEmbedを選択し、TitleにJumpableと入力してください。
State Machineについて
ここでEdit Graphを押すと以下のような画面が出るはずです。
画面構成は基本Script Machineと同じですが、右側が状態遷移図となっています。
この状態遷移図の"状態"とは、Script Machineのことだと考えてもらって大丈夫です。
ここで、中央のStart
をクリックすると先程のScript Machineの編集画面と似たものが出てきたのがわかると思います(下図)。
状態の作成
それでは、状態を作っていきましょう。
まず、右クリック->Create Script State
を選択して、TitleにJumping
と入力します。
また、初期状態であるStartの名前を変更してGrounded
とします。
これで、ジャンプ中の状態Jumping
と接地中の状態Grounded
が作成できました。
遷移の作成
次に、遷移を作成していきます。
Grounded
を右クリック->Make Transition
で矢印をJumping
につなげます。
同様にJumping
からGrounded
へも矢印をつなげます。
しかし、線をつないだだけでは”なにがあったら状態が変わるか”が記述できていません。
次は、この遷移条件を記述します。
遷移条件
まず、Grounded
からJumping
への遷移を作成しましょう。
今回はGrounded
からJumping
への遷移条件は、「何かのキーが押された」こととします。
Grounded
からJumping
への遷移の間にある黄色の6角形をダブルクリックしましょう。
すると以下のような画面が出るはずです。
次にOn Update
ノード、Input Get Any Key
ノード、If
ノードを作成し、以下のようにつないでください。
これで、「Grounded
状態で何かのキーが押されていたらJumping
状態へ遷移する」という処理になります。
次は、Jumping
からGrounded
への遷移を作成しましょう。
今回はJumping
からGrounded
への遷移条件は、「Floorという名前のオブジェクトと接触した」こととします。
上と同様に今度はJumping
からGrounded
の遷移の間にある黄色の6角形をダブルクリックし、以下のようなグラフを作成してください。
これで、「Jumping
状態でFloorという名前のオブジェクトと接触したらGrounded
状態へ遷移する」という処理になります。
ジャンプ処理
遷移も記述できたところで、肝心のジャンプ処理を記述していきましょう。
ジャンプ処理は、今回「Jumping
状態に入った瞬間、上方向に力をかける」ことで実現します。
では、早速Jumping
をダブルクリックして以下のように処理を記述しましょう。
ここで、On Enter State
は「この状態に入った直後に発火するイベント」、On Exit State
は「この状態から出る瞬間に発火するイベント」です。
なお、このままでは上に飛ぶ力が強すぎるかもしれません。
その場合、Add ForceノードのForce値や、Rigidbody2DのGravity Scaleを調整しましょう。
(記事の上の方で貼った動作例ではRigidBody2DのGravity Scaleを10にしています。)
これで、プレイヤーのジャンプは実現できました。
今回の例ではState Machineをそれほど活用できていませんが、最終的には各状態でAnimationの管理を行ったり、状態を増やしてより多彩な処理を行ったりということが可能です。
まとめ
今回はVisual Scriptingを用いたシンプルな横スクロールゲームの制作方法を紹介しました。
Visual Scriptingを用いてノードをつないだグラフを作成することで、わかりやすく簡単に、障害物を動かしたりプレイヤーをジャンプさせたりできました。
Visual Scriptingでは、処理をグラフィカルに見ることができるため非エンジニアでもわかりやすい点や、素早くトライアンドエラーがまわしやすい点などがメリットとして挙げられます。
また、今回紹介したState Machineはゲーム制作の上で色々な応用が考えられる強力な機能だと思います。
今回使用していない機能(カスタムイベント・サブグラフなど)も沢山あるので、興味があれば調べてみて下さい。
「Visual Scripting使ったことないけどどういうものか気になる!」と思っている方がこの記事を読むことで「Visual Scriptingなんとなくわかったぜ!」となっていれば幸いです。
最後に
この記事は サムザップ Advent Calendar 2021 の12/16の記事です。
昨日の記事は @ozaki_shinya さんによるUnityでシーン遷移時にパラメーターを渡す方法でした。
明日は@higuchi_yutaさんの「【Unity】ATBシステムにおける新ルールの実装コストを削減した設計」です。