#初めに
先輩に面白いアセットを教えていただいたので実際に買って遊んでみた。
そのレビューとして、ざっくり理解した使い方を書いていこうと思う
基本的な機能の説明
UnityでScratch-Likeな機能が実装できる有料アセット
値段は25ドルなので2600円くらい?(2021/02/20現在)
Play Mode Blocks Engine
大部分はScratchと同じ。
Blockを組んで何らかの実行イベントを起こすと組んだブロックに応じて処理が走る。
全体
外観はこんな感じ。(いくつか自分で適当にボタンやテキスト追加してます)
ブロックは2種類ある
ブロックの分類は7種類ある
各targetObjectがそれぞれ独自のPG環境を持つ
- シーン上に複数のtargetObjectがあり、それぞれにCode Blockのセットがある時もある。抽象化の目的で、各targetObjectはそれぞれ独自のCanvasを持つ。
- ブロックをプログラミング環境にドロップできる
- 目的のブロックを押したまま/右クリックすることで、アクションを含むメニューパネルを開くことができる。(コピーと削除)
- コードは保存及びロードができる
Codeの保存機能の仕組み
- 現在のキャンバスブロックを単純なテキストベースのファイル(.BE)に変換し保存する。
- 任意のテキストエディタで開くことができ、データの操作が容易である。
- 逆に、ブロックのテキストへの変換をするカスタム関数がある。
- 保存したコードは、Application.persistentDataPathからUnityによって提供される永続データディレクトリの「SavedCodes」というフォルダに保存される。
- [保存]ボタンをクリックするとポップアップメニューが開く
Codeのロード機能の仕組み
Joy Stickについて
Model Class
BE TargetObject
ScratchでいうSpriteみたいなもの。再生ボタンや他のトリガーを介して自身のトリガーがActiveになった時に処理が走る
BE Block
動かすコードブロックのこと。大きく次の5つに大別される
- Trigger
- ブロックの塊の上に配置。
- イベントリスナーとして動作
- ブロックの塊をActiveにするのに必要なFunction Block
- Simple
- サイクルごとに1回実行される
- 子ブロックをラップしないFunction Block
- Loop
- ループ命令を実行するFunction Block
- ループ条件が満たされている場合に、実行される子ブロックをラップ
- Conditional
- 条件付き命令を実行
- 条件が満たされた場合に実行される子ブロックをラップ
- Operation
- Function Blockのヘッダーに配置される
- 真偽値を文字列で返す
BE Inputs
各ブロックのヘッダーには入力値を入力/選択する箇所がある。
これらの値は、BEInputと呼ばれる型で、BEBlockオブジェクトに格納されている。
BEInputには、文字列および浮動小数点値としての入力のマップがある。
- string[ ]型のstringValues
- float[ ]型のnumberValues
これらはフラグisStringを持つ。(少なくとも1つの入力値を数値に変換できない場合にtrueになる)
【2つの入力を持つBE BlockオブジェクトbeBlockの例】
最初の入力値はbeBlock.BeInputs.stringValues [0]またはbeBlock.BeInputs.numberValues [0]で呼び出す。
2番目の入力値は、beBlock.BeInputs.stringValues [1]またはbeBlock.BeInputs.numberValues [1]で呼び出す。
すでに実装されているブロックでは文字列と数値の両方の入力を考慮しているため、プレーヤーは特に型を気にせずにブロックを使用できる。
BE CONTROLLER
プログラミング環境に配置され、ターゲットオブジェクトに関連付けられたすべてのActiveなブロック処理を実行。
大きく次の役割を持つ。
- トリガーブロックを開始
- すべてのブロックグループを停止
- 対応するブロックグループシーケンスの次のブロックをアクティブ化
- その他のメソッド
BE Instruction
BE Instructionは、コントローラーによって呼び出されるメソッド定義するコントローラークラス
BEFunctionメソッドとBEOperationメソッドの一方または両方が含まれる。
BE Variables
実際のコーディング手法にできるだけ近くするため、Function Blockとして使用したり、Function Blockの入力値として設定したりする変数のこと。
BE変数には、変数の名前と値を格納するBEVariableと呼ばれるカスタムタイプのリストからアクセスする。
BE CONTROLLERには、SetVariable(string、string)とGetVariable(string)がすでにある。
ColorとSoundに対応するBE変数Listもある
Play Next Method
名前の通り、次の命令処理に移行することを通知するメソッド。
BEFunctionメソッドの中には次のどちらかは必須
- PLAY NEXT OUTSIDE:Simpleの最後やLoopの最後、Conditionalで条件を満たさない場合などに呼ばれる
- PLAY NEXT INSIDE:Trigger、Loop、Conditionalで条件を満たす場合などに呼ばれる
プログラミング環境に組んだブロックが実行される仕組み
PlayNextMethodによって再帰的な構造になっている
- 何らかのトリガーで各BlockのisActiveがtrueになったら処理が動く。
- 処理が終わったらPlayNextOutsideが呼ばれ、次のBlockに入っていく
- その際に次のBlockのisActiveが変わる処理が走る(多分)
Scene
BE Controllerインスペクターの下部には、Sceneと呼ばれるセクションがある。
シーンで現在アクティブなすべてのターゲットオブジェクトを識別し、そのプログラミング環境のActivationを決定する。
次節のWorkshopを用いて複数のTargetObjectを用いる場合は、BE Controllerの持つ「Scene」からSingleSelectionを選択しておけば、一度に表示されるプログラミング環境を1つに制限できる。
Workshop
BE Controllerのインスペクターの下部には、Workshopと呼ばれるセクションがある。
いくつかの変数を設定するだけで新しいTargetObjectやBlockを作成できる
オリジナルのブロックを作る方法
BE Controllerのインスペクターの下部のWorkshopから、いくつかの変数を設定するだけで新しいターゲットオブジェクトとブロックを作ることができる。まずはBlockタイプと動作ルールを設計する。
今回は例として、入力値を受け取って指定回数あいさつをConsole表示するようなBlockを作ってみる
以下の処理はWorkshopセクションで行う
- Blockの表示名とタイプを決める。(今回は名前はFuga、ブロックタイプはSimple)
- Blockヘッダー作成する。表示するテキストと入力タイプを正しい位置に配置してHeaderGuidelineを設定する
HeaderGuideline記入例は以下の通り
[inputfield = 1]
回あいさつする
色々この辺を設定したら「ビルドブロック」ボタンを押すと、「ブロックと命令が作成されました」というメッセージが表示される。
スタックに命令をインポートしようとしています...」、メッセージが消えるまで待てば完了。
結果として、以下が作成される
- スクロールビューに表示される新しいブロック(名前はFuga)
- BE Instruction Script フォルダ内に新しいスクリプト(Fuga.cs)
- Instruction Stackにコンポーネントとして追加されたInstruction
- 新しいプレハブ(resources/prefabs/Blocks/Fuga.prefab)
スクロールビューでは一番上に生成されるので適当な場所に置き直すこと
ここまででプログラミング環境にD&Dできるブロックは完成したので、次はオブジェクトとスクリプトを対応させていく
新しく作成されたスクリプトには、命令動作のコーディングをするために必要なテンプレートがすでに含まれている
以下は作成されたばかりのスクリプト(コメントは適宜加えた)
using UnityEngine;
using System.Collections;
using System;
public class Fuga : BEInstruction
{
// Use this for Operations
public override string BEOperation(BETargetObject targetObject, BEBlock beBlock)
{
string result = "0";
//入力値に関してここで色々いじったり判定したりして結果を0か1の文字列で返す(なんでboolじゃないのかな?)
return result;
}
// Use this for Functions
public override void BEFunction(BETargetObject targetObject, BEBlock beBlock)
{
// 入力値を受け取るときはこんな感じ
string option = beBlock.BeInputs.stringValues[0];
// 子要素のBlockに進むときはPlayNextInside(beBlock)、それ以外はPlayNextOutside(beBlock)を用いる。BEFunctionメソッド内に必須
BeController.PlayNextOutside(beBlock);
}
}
今回はコンソール表示をしたいので、BEFunctionの処理を次のように記述
public override void BEFunction(BETargetObject targetObject, BEBlock beBlock)
{
int option = int.Parse(beBlock.BeInputs.stringValues[0]);
for (int i = 0; i < option; i++)
{
Debug.Log("おはよう");
}
BeController.PlayNextOutside(beBlock);
}
最後に
25ドルでここまで遊べるのはなかなか強い。
一点気になるとすればブロックを繋げるのが少々難しい…
その辺の判定とかUIを修正すれば面白いものが作れそうな有料アセットだと思った。
ここまで読んでいただきありがとうございました。
この記事が何かのお役に立てたなら幸いです。