6. Main Logicの挙動作成

前回までの作業がまだ済んでいない場合は、ブロック崩しの作成方法から前回までのチュートリアルを先に済ませてください。

ここまではゲームクリアとゲームオーバーの表示切替を別々のオブジェクトで行っていましたが、ゲームの進行をMain Logicオブジェクトで管理するように変更します。
ゲームの状態はBlackboard Assetで共有し、各オブジェクトはBlackboardのData Linkを介してゲームの状態にアクセスするようにします。

Blackboard Assetの作成

  • ProjectウィンドウのLogicフォルダを選択
  • +ボタンをクリック
  • メニューからLogic Toolkit/Blackboardを選択
  • 名前をMain Scene Blackboardに変更

Main Scene Blackboardの編集

作成する変数は以下の通りです。

変数名説明
IsPlayingboolゲームのプレイ中(ボールが動いてブロックを壊せる間)にtrueとなる。
falseからtrueに切り替わった場合にボールが移動開始する。
trueからfalseに切り替わった場合はゲーム終了としクリア判定を行う。
IsGameClearboolゲーム終了時にクリアした場合にtrueとなる。
ゲームオーバーの場合はfalseとなる。

IsPlaying変数の作成

  • Main Scene Blackboardを選択し、InspectorウィンドウでBlackboardの+ボタンをクリック
  • 変数作成メニューからPrimitive/boolを選択
  • 名前をIsPlayingに変更

IsGameClear変数の作成

  • Inspectorウィンドウで、Blackboardの+ボタンをクリック
  • 変数作成メニューからPrimitive/boolを選択
  • 名前をIsGameClearに変更

Main LogicにLogic Behavior追加

  • Main Logicオブジェクトを選択
  • InspectorウィンドウのAdd Componentボタンをクリック
  • Logic Toolkit/Logic Behaviorを選択してLogic Behaviorコンポーネントを追加
  • Logic BehaviorのEditボタンをクリックし、Logic Editorウィンドウを開く

Main LogicのLogic Behaviorを編集

Main Logicの状態の進行管理にStateノードを使用します。
作成するステートは以下の通りです。

ステート名説明
Game Startゲーム開始直後の状態。
Game Startステートがアクティブの間、Game Startオブジェクトを表示する。
Submitボタンを押した際にGame Playingステートに遷移する。
Game Playingゲームをプレイ中の状態。
ボールが移動し、ブロック崩しを楽しめる。
IsPlaying変数がfalseになったらIsGameClearを判定し、Game ClearステートかGame Overステートに遷移する。
Game Clearブロックをすべて破壊し、ゲームクリアした状態。
Game Clearオブジェクトを表示する。
Submitボタンを押した際にシーンをリロードする。
Game Overボールが落下して、ゲームオーバーになった状態。
Game Overオブジェクトを表示する。
Submitボタンを押した際にシーンをリロードする。

ステートは実行ノードの一種として用意しています。
いままで使用してきたActionノードやBranchノードなどとStateノードを接続することで一連の流れの中にステートも組み込めます。

Main Sceneデータリンクの作成

  • サイドパネルのBlackboardタブを選択
  • Data Linkタブを選択
  • +ボタンをクリック
  • 名前をMain Sceneに変更
  • Share TypeフィールドをSceneに設定
  • Blackboard AssetフィールドをLogic/Main Scene Blackboardアセットに設定

Data Link機能を利用してBlackboardを参照すると、Share TypeとTagとBlackboard Assetが共通のData Linkは共有され、同一変数にアクセスできるようになります。

Game Startステートの作成

  • Startノードの実行ポートをドラッグ&ドロップし、ノード作成メニューを開く
  • Scriptsタブを選択
  • 一覧からStateを選択
  • 名前をGame Startに変更

GameObject.SetActiveコンポーネントの追加

  • Game StartステートのComponentsフィールドの+ボタンをクリック
  • Scriptsタブを選択
  • 検索欄にGameObject SetActiveと入力
  • 一覧からGameObject.SetActive(bool value)を選択

いままではActionノードで使用してきたGameObject.SetActive(bool value)ですが、ActionComponentというスクリプトで実装されていますので、Stateノードなどのコンポーネントとしても利用可能です。

GameObject.SetActiveコンポーネントの編集

  • MethodsフィールドをOn Activatedのみに変更
  • TargetフィールドにCanvas/Game Startオブジェクトを設定
    以下のいずれかの方法で設定できます。
    • SelfをValueに変更し、オブジェクトフィールドでCanvas/Game Startオブジェクトを設定
    • Selfのまま、HierarchyウィンドウからCanvas/Game StartオブジェクトをTargetフィールドにドラッグ&ドロップ
  • Valueフィールドをチェック

ActionComponentをStateノードに使用した場合は、Methodsフィールドが追加されます。
ActionComponentは処理をすぐに実行するだけのスクリプトですので、Methodsフィールドの設定で実行するタイミングを制御します。
今回のOn Activatedはステートがアクティブになったときに実行される設定です。

IsPlaying変数の設定コンポーネントの追加

  • Main SceneデータリンクのIsPlaying変数をGame StartステートのComponentsの一番下にドラッグ&ドロップし、コンポーネント追加メニューを開く
  • 一覧からSet Variableを選択

IsPlaying変数の設定コンポーネントの編集

  • MethodsフィールドをOn Activatedのみに変更

GameObject.SetActiveコンポーネントの追加

  • Game StartステートのComponentsフィールドの+ボタンをクリック
  • Scriptsタブを選択
  • 検索欄にGameObject SetActiveと入力
  • 一覧からGameObject.SetActive(bool value)を選択

GameObject.SetActiveコンポーネントの編集

  • MethodsフィールドをOn Deactivatedのみに変更
  • TargetフィールドにCanvas/Game Startオブジェクトを設定
    以下のいずれかの方法で設定できます。
    • SelfをValueに変更し、オブジェクトフィールドでCanvas/Game Startオブジェクトを設定
    • Selfのまま、HierarchyウィンドウからCanvas/Game StartオブジェクトをTargetフィールドにドラッグ&ドロップ

今回のOn Deactivatedはステートが非アクティブになったときに実行される設定です。

Input.GetButtonDownコンポーネントを追加

  • Game StartノードのComponentsの+ボタンをクリック
  • Membersタブを選択
  • 検索欄にInput GetButtonDownと入力
  • 一覧からUnityEngine.InputGetButtonDown(string buttonName)を選択

bool型が戻り値のメンバーはEvaluateComponentというスクリプトで実装されます。
EvaluateComponentは何かを評価するためのノード用コンポーネントです。
今回はボタン押下を判定するInput.GetButtonDown(string buttonName)をStateノードに使用して、Submitボタンの押下を評価してステートを遷移させます。

Input.GetButtonDownコンポーネントの編集

  • Button NameフィールドをSubmitに設定

Game Playingステートの作成

  • Input.GetButtonDownコンポーネントのSignalフィールドのシグナルポートをドラッグ&ドロップして、ノード作成メニューを開く
  • Scriptsタブを選択
  • 一覧からStateを選択
  • 名前をGame Playingに変更

出力シグナルポートを直接実行ノードに接続すると、条件を満たしてシグナルがオンになったタイミングで接続先ノードに遷移します。

IsPlaying変数の設定コンポーネントの追加

  • Main SceneデータリンクのIsPlaying変数をGame PlayingステートのComponentsにドラッグ&ドロップして、コンポーネント追加メニューを開く
  • 一覧からSet Variableを選択

IsPlaying変数の設定コンポーネントの編集

  • MethodsフィールドをOn Activatedのみに変更
  • Is Playingフィールドをチェック

Bool Equalsコンポーネントの追加

  • Game PlayingステートのComponentsの+ボタンをクリック
  • Scriptsタブを選択
  • 検索欄にBool Equalsと入力
  • 一覧からBool Equalsを選択

IsPlaying変数の取得ノードの作成

データポートをドラッグ&ドロップして変数アクセスノードを作成する方法もあります。

  • Bool EqualsコンポーネントのValue 1フィールドの入力ポートをドラッグ&ドロップし、ノード作成メニューを開く
  • Scriptsタブを選択
  • 検索欄にIsPlayingと入力
  • 一覧からCompute/Variables/DataLink/Main SceneIsPlaying [Get] (Compute)を選択

Time.timeScaleノードの作成

ゲームの結果表示中はTime.timeScaleを0にしてポーズ状態にしてみましょう。

  • Bool EqualsコンポーネントのSignalフィールドのシグナルポートをドラッグ&ドロップし、ノード作成メニューを開く
  • Membersタブを選択
  • 検索欄にTime timeScaleと入力
  • 一覧からUnityEngine.TimetimeScale [Set]を選択
  • ノードの種類選択メニューからActionを選択

シグナルポートはStateだけでなくActionやTask、Branchなどのフロー制御ノードに遷移できます。

Branchノードの作成

IsGameClear変数を判定して処理を分岐します。

  • Time.timeScaleノードの遷移ポートをドラッグ&ドロップし、ノード作成メニューを開く
  • Scriptsタブを選択
  • 一覧からFlow Controls/Branchを選択

IsGameClear変数の取得ノードの作成

  • BranchノードのConditionフィールドの入力ポートをドラッグ&ドロップし、ノード作成メニューを開く
  • Scriptsタブを選択
  • 検索欄にIsGameClearと入力
  • 一覧からCompute/Variables/DataLink/Main SceneIsGameClear [Get] (Compute)を選択

Game Clearステートの作成

  • BranchノードのTrueフィールドの遷移ポートをドラッグ&ドロップし、ノード作成メニューを開く
  • Scriptsタブを選択
  • 一覧からStateを選択
  • 名前をGame Clearに変更

GameObject.SetActiveコンポーネントの追加

  • Game ClearステートのComponentsフィールドの+ボタンをクリックし、コンポーネント追加メニューを開く
  • Scriptsタブを選択
  • 検索欄にGameObject SetActiveと入力
  • 一覧からGameObject.SetActive(bool value)を選択

GameObject.SetActiveコンポーネントの編集

  • MethodsフィールドをOn Activatedのみに設定
  • TargetフィールドにCanvas/Game Clearオブジェクトを設定
    以下のいずれかの方法で設定できます。
    • SelfをValueに変更し、オブジェクトフィールドでCanvas/Game Clearオブジェクトを設定
    • Selfのまま、HierarchyウィンドウからCanvas/Game ClearオブジェクトをTargetフィールドにドラッグ&ドロップ
  • Valueフィールドをチェック

Game Overステートの作成

  • BranchノードのFalseフィールドの遷移ポートをドラッグ&ドロップし、ノード作成メニューを開く
  • Scriptsタブを選択
  • 一覧からStateを選択
  • 名前をGame Overに変更

GameObject.SetActiveコンポーネントの追加

  • Game OverステートのComponentsフィールドの+ボタンをクリックし、コンポーネント追加メニューを開く
  • Scriptsタブを選択
  • 検索欄にGameObject SetActiveと入力
  • 一覧からGameObject.SetActive(bool value)を選択

GameObject.SetActiveコンポーネントの編集

  • MethodsフィールドをOn Activatedのみに設定
  • TargetフィールドにCanvas/Game Overオブジェクトを設定
    以下のいずれかの方法で設定できます。
    • SelfをValueに変更し、オブジェクトフィールドでCanvas/Game Overオブジェクトを設定
    • Selfのまま、HierarchyウィンドウからCanvas/Game OverオブジェクトをTargetフィールドにドラッグ&ドロップ
  • Valueフィールドをチェック

Signal Evaluationノードの作成

Game ClearステートとGame OverステートはともにSubmitボタンを押した際にシーンをリロードする挙動となっています。
遷移条件が場合はSignal Evaluationノードを使用すると判定を共通化できます。

  • Game Clearステートのシグナルポートをドラッグ&ドロップして、ノード作成メニューを開く
  • Scriptsタブを選択
  • 一覧からSignals/Signal Evaluationを選択

Stateのヘッダ部にあるシグナルポートはステートがアクティブの間オンになります。
このシグナルポートからSignal Evaluationノードを接続すると、ステートがアクティブの間の遷移条件判定が行えるようになります。

Input.GetButtonDownコンポーネントを追加

  • Signal EvaluationノードのConditionsの+ボタンをクリック
  • Scriptsタブを選択
  • 検索欄にInput GetButtonDownと入力
  • 一覧からInput.GetButtonDown(string buttonName)を選択

Input.GetButtonDownコンポーネントの編集

  • Button NameフィールドにSubmitを設定

Game OverステートとSignal Evaluationノードの接続

  • Game OverステートのシグナルポートをSignal Evaluationノードの入力ポート(Game Clearステートと接続されているポート)にドラッグ&ドロップして接続

同じ入力ポートに複数のシグナルワイヤーを接続している場合は、いずれか一つでもシグナルがオンの場合は真となります。

Time.timeScaleノードの作成

シーンのリロードの前にTime.timeScale1に戻します。

  • Signal Evaluationノードの遷移ポートをドラッグ&ドロップし、ノード作成メニューを開く
  • Scriptsタブを選択
  • 検索欄にTime timeScaleと入力
  • 一覧からSet Time.timeScale (Action)を選択

Time.timeScaleノードの編集

  • Time Scaleフィールドを1に変更

SceneManager.LoadSceneノードの作成

  • Time.timeScaleノードの遷移ポートをドラッグ&ドロップし、ノード作成メニューを開く
  • Membersタブを選択
  • 検索欄にSceneManager LoadSceneと入力
  • 一覧からUnityEngine.SceneManagement.SceneManagerLoadScene(string sceneName)を選択
  • ノードの種類選択メニューからActionを選択

SceneManager.LoadSceneノードの編集

  • Scene NameフィールドをBlockBreakingに変更

Main Logicのグラフ

ここまで作成するとグラフは以下のようになっています。

Ballの挙動変更

IsPlaying変数がtrueになった際に移動開始するように挙動を変更します。

変更の準備

  • Player/Ball SocketにあるBallオブジェクトを選択
  • BallオブジェクトのLogic BehaviorをLogic Editorウィンドウで開いておく

Main Sceneデータリンクの作成

  • サイドパネルのBlackboardタブを選択
  • Data Linkタブを選択
  • +ボタンをクリック
  • 名前をMain Sceneに変更
  • Share TypeフィールドをSceneに設定
  • Blackboard AssetフィールドをLogic/Main Scene Blackboardアセットに設定

IsPlaying変数の変更イベントノードの作成

  • Startノードを削除
  • Main SceneデータリンクのIsPlaying変数をStartノードがあった辺りのドラッグ&ドロップし、ノード作成メニューを開く
  • 一覧からChange Variable Event (Event)を選択

Branchノードの作成

  • IsPlaying変数の変更イベントノードのIs Playingフィールドの出力ポートをドラッグ&ドロップし、ノード作成メニューを開く
  • Scriptsタブを選択
  • 一覧からFlow Controls/Branchを選択

Branchノードとの接続

  • IsPlaying変数の変更イベントノードの実行ポートをBranchノードの入力ポートにドラッグ&ドロップして接続
  • BranchノードのTrueフィールドの遷移ポートをTransform.SetParentノードの入力ポートにドラッグ&ドロップして接続

Ballのグラフ

ここまで作成するとグラフは以下のようになっています。

Blocksの挙動変更

すべてのオブジェクトが破壊できた場合のクリア判定をMain Logic側に通知するように変更します。
今回はMain Scene BlackboardをData Link機能で共有し、IsGameClear変数をtrueにした後、IsPlaying変数をfalseにすることでMain LogicがGame Clearステートに切り替わります。

変更の準備

  • Blocksオブジェクトを選択
  • BlocksオブジェクトのLogic BehaviorをLogic Editorウィンドウで開いておく

Main Sceneデータリンクの作成

  • サイドパネルのBlackboardタブを選択
  • Data Linkタブを選択
  • +ボタンをクリック
  • 名前をMain Sceneに変更
  • Share TypeフィールドをSceneに設定
  • Blackboard AssetフィールドをLogic/Main Scene Blackboardアセットに設定

IsGameClear変数の設定ノードの作成

  • Game ClearオブジェクトをアクティブにしているGameObject.SetActiveノードを削除
  • Main SceneデータリンクのIsGameClearをGameObject.SetActiveノードがあった辺りにドラッグ&ドロップし、ノード作成メニューを開く
  • 一覧からSet Variable (Action)を選択

IsGameClear変数の設定ノードの編集

  • Is Game Clearフィールドをチェック

IsGameClear変数の設定ノードへの接続

  • Int Equalsノードの実行ポートからIs Game Clear変数の設定ノードの入力ポートにドラッグ&ドロップして接続

IsPlaying変数の設定ノードの作成

  • Main SceneデータリンクのIsPlayingをIsGameClear変数の設定ノードの右隣辺りにドラッグ&ドロップし、ノード作成メニューを開く
  • 一覧からSet Variable (Action)を選択

IsPlaying変数の設定ノードへの接続

  • IsGameClear変数の設定ノードの遷移ポートをIsPlaying変数の設定ノードの入力ポートにドラッグ&ドロップして接続

Blocksのグラフ

ここまで作成するとグラフは以下のようになっています。

Wall Bottomの挙動変更

ボールが落下した場合のゲームオーバー判定をMain Logic側に通知するように変更します。
今回はMain Scene BlackboardをData Link機能で共有し、IsGameClear変数をfalseにした後、IsPlaying変数をfalseにすることでMain LogicがGame Overステートに切り替わります。

変更の準備

  • Walls/Wall Bottomオブジェクトを選択
  • Wall BottomオブジェクトのLogic BehaviorをLogic Editorウィンドウで開いておく

Main Sceneデータリンクの作成

  • サイドパネルのBlackboardタブを選択
  • Data Linkタブを選択
  • +ボタンをクリック
  • 名前をMain Sceneに変更
  • Share TypeフィールドをSceneに設定
  • Blackboard AssetフィールドをLogic/Main Scene Blackboardアセットに設定

IsGameClear変数の設定ノードの作成

  • Game OverオブジェクトをアクティブにしているGameObject.SetActiveノードを削除
  • Main SceneデータリンクのIsGameClearをGameObject.SetActiveノードがあった辺りにドラッグ&ドロップし、ノード作成メニューを開く
  • 一覧からSet Variable (Action)を選択

IsGameClear変数の設定ノードへの接続

  • GameObject.Destroyノードの遷移ポートからIs Game Clear変数の設定ノードの入力ポートにドラッグ&ドロップして接続

IsPlaying変数の設定ノードの作成

  • Main SceneデータリンクのIsGameClearをIsGameClear変数の設定ノードの右隣辺りにドラッグ&ドロップし、ノード作成メニューを開く
  • 一覧からSet Variable (Action)を選択

IsPlaying変数の設定ノードへの接続

  • IsGameClear変数の設定ノードの遷移ポートをIsPlaying変数の設定ノードの入力ポートにドラッグ&ドロップして接続

Wall Bottomのグラフ

ここまで作成するとグラフは以下のようになっています。

Main Logicの挙動確認

プレイしてゲームの流れの挙動を確認しましょう。

  • プレイ開始直後、Ballが移動しないことを確認
  • Playerの移動に合わせてBallが連動していることを確認
  • Submitボタン(デフォルトではSpaceキーもしくはEnterキー)を押すと移動開始することを確認
  • すべてのブロックを壊した場合に、Game Clearが表示されることを確認
  • Game Clearが表示中にSubmitボタンを押すとシーンがリロードされることを確認
  • シーンリロード後も繰り返し動作することを確認
  • ボールが落下した場合に、Game Overが表示されることを確認
  • Game Overが表示中にSubmitボタンを押すとシーンがリロードされることを確認

次回

次回は7. PhysicsのBounce Thresholdの設定を行います。

完了を投稿

ここまでの作業完了をSNSに投稿する場合はこちら。