残り課題
今回 ブロックの造形(見た目をGeometoryScriptで成型)
今回 ステージ生成(データテーブル)
残 ステージセレクト画面
残 解像度調整(多分やらない)
残 パッケージ化
ここまで出来たら「ブロック崩しを作ろう」の企画は完了。
今回終わらせる予定だったのですが、ステージ生成(データテーブル定義)が予想以上に重かったので分割しました。
使用しているバージョン
Unreal Engine 5.3.2
Geometory Scriptを使ったブロック造形
見かけ用のDynamicMeshActorを作成
ターゲットのブロックがあまりにシンプルなので少し手を加えます。
流れは以前やったものと同じ

ですが

公式ドキュメントより抜粋
とあるので今回はDynamicMeshActorで作成(前回はGeneratedDynamicMeshActor)。
GeneratedDynamicMeshActorはビューポート上で目で確認しながら造形が可能(だけどエディタのみ動作)。
また前回も言ったように、どちらもNanite と Lumenはサポート外。

Construction Scriptにカプセル型のmeshを追加(Append Capsule)。
変更が必要な設定値は全て変数へ昇格し、インスタンス編集可能にチェック。

設定したパラメータは上記。
一度GeneratedDynamicMeshActorで大きさを計って、メモして設定しました。

MaterialはMetarilc属性をいれました(色も多少変更)
collision判定用のcubeを埋め込む
DynamicMeshActorだと当たり判定が難しいので、当たり判定は埋め込んだキューブで行います。


位置を確認したら


コリジョンのSimulation Generates Hit Events(ON)
レンダリングのVisible(OFF)
イベントグラフのOn Component Hit判定もこのCubeに対して行います。
親クラスを変更

前回のブロック作成と同じく、GMS_TargetParent(DynamicMeshActorの子クラス)を作り、各ブロックはGMS_TargetParentを親クラスとすることで、Get All Actors Of Classで一括で配列取得できるようにします。
結果
Before

After

設置は手置きなのでズレてますが、次で整えます。
ステージ生成
基本として、アクタの位置(Location)は中心点のことを指す。
ピボットポイント(矢印が出てる場所)ではない。
V+ALT+マウスホイールクリックでピボットポイントの移動はできますが、中心点(Location)が変わるわけではないので注意。
ピボットポイントを移動してない場合は、おそらくピボットポイント=中心点。
つまり、あるアクタに対するGet Actor LocationとGet Actor Boundsのoriginは同じ座標を指す。

ただし、DynamicMeshActorや複数のStaticMeshで構成されたアクタの場合は少し異なるようです(GetActorLocationで確認)。
イメージ的には動的に作成されるDynamicMeshActorは描画起点=中心点となる。
ブロックとフロアの大きさを測る
まずはブロックの大きさと、ステージサイズを測って調整します。

適当なグラフに配置してGet Actor Boundsを使ってXYZの大きさを調査。
中心点からXYZへの距離が出力されるので、2倍にすることで各辺の長さが算定できます。
《調査結果》
対象 | X | Y | Z |
---|---|---|---|
ターゲットブロックの大きさ | 480 | 760 | 320 |
フロア(BP_BaseBlock)の大きさ | 8000 | 6000 | 100 |
ブロック配置設計
現在使用しているステージのフロアサイズはX軸8000/Y軸6000
中心点は(19020,4190,20) ※Z軸は床の表面の高さ
ターゲットブロックが幅760なので、7つ並べると5320
5320+6(ブロックの隙間)+2(左右の隙間)=6000になればいいので
設計数値
ブロック間の隙間(左右)=20
左右の隙間=280
ブロック間の隙間(上下)=120
上の隙間=500
配置図は以下のようになる

⇕X軸 ⇔Y軸
横7ブロックの中心Y座標
1ブロック目:1470(1190+280)※中心点ではなく左端で算定
2ブロック目:2250 (1470+760+20)
3ブロック目:3030 (2250+760+20)
4ブロック目:3810 (3030+760+20)
5ブロック目:4590 (3810+760+20)
6ブロック目:5370 (4590+760+20)
7ブロック目:6150 (5370+760+20)
縦4ブロックの中心X座標
縦(X座標)の配置に関しては横よりもアバウトに設定
ブロックの隙間=120
上の隙間=500
1ブロック目:22280 (23020-500-240)
2ブロック目:21680 (22280-480-120)
3ブロック目:21080 (21680-480-120)
4ブロック目:20480 (21080-480-120)
データテーブル(座標定義)を作成
①Y軸用(7列)配置座標用構造体を作成
(右クリックメニュー)ブループリント>構造体

②X軸用(4行)のブロック有無を記載するデータテーブルを作成
(右クリックメニュー)その他>データテーブル
行データは①で作った構造体
4行7列のブロック(4行7列)の中心座標(X,Y)をdatatableに打ち込むと

(イベントグラフ作成後の画像)これを元に全ての位置にブロックを生成すると

こんな感じの生成結果になります。
データテーブル(ステージブロック定義)を作成
上では4行7列全てに100点用のターゲットを配置しましたが、ステージ毎に特色を持たせるために実際は数を減らしたり、高得点ブロックを混ぜたりします。
そのステージ毎の定義ファイル(datatable)を作成。
①Y軸用(7列)のブロック有無を記載する構造体を作成
(右クリックメニュー)ブループリント>構造体

②X軸用(4行)のブロック有無を記載するデータテーブルを作成
(右クリックメニュー)その他>データテーブル
行データは①で作った構造体

0:配置なし
1:100点ブロック
2:400点ブロック
3:1000点ブロック
上画像は全ての出現場所に100点ブロックのみを出現させるケース。
ステージ生成(イベントグラフ)
形だけのプレイヤーポーン(BP_BarControl)に記述していきます。
位置データテーブル(DT_BlockPoint)の座標を参照し、その位置に何を配置するかを記載したブロックデータテーブル(DT_BreakBlockS00)で指定されたブロック(配置しない/100点/400点/1000点)を配置する。
要は、2つのデータテーブルを使って、「どこに」「何点のブロック」という対象を上手く自動配置していく。
位置データテーブルは1つのみ作成。
ブロックデータテーブルはステージ毎に1つずつ作成。
今回使用するDataTable
位置データテーブル(DT_BlockPoint)

28マス分のブロックのスポーン座標が入っています。
ブロックデータテーブル(DT_BreakBlockS00)

28マス分の配置ブロックの種類のデータが入ってます(ステージデータ)
0:配置なし
1:100点ブロック
2:400点ブロック
3:1000点ブロック
これを元にステージ生成を行い

となるようにします。
EventBeginPlayの最後にCreateStage(カスタムイベントを作成)

CreateStageの中身を実装
全体像

使用変数

スマートなコーディングは諦めました…
大まかな処理概要
左上部:データテーブルを1行ずつ取得(4回ループ)
右上部:データターブル構造体(1行分)を配列(array)に格納
下部:配列に従い3種類のブロックを配置していく(7回ループ)
構造体(データテーブルから入手したデータ)がこんな扱いづらいとは思いませんでした。
最終的には力業で(扱いやすい)Arrayに全て放り込むことに。
もっと汎用的なコーディングにしたかったのですが…
左上

Add Custom Event | Create Stageイベントの開始地点 |
For Loop | 4行分のループ |
Get Data Table Row | Row Nameをキーにデータテーブル(DT_BlockPoint)から行データを取得 Row Nameは0~3のname型(ここの処理の為にそうしてます)なのでIndex(0~3)を型変換してキーとして使用 Integer⇒string⇒nameと変換(直接変換はできなかった) 取得した行データ(7カラム)はTargetPoint(構造体変数)に格納 |
Get Data Table Row | Row Nameをキーにデータテーブル(DT_BreakBlockS00)から行データを取得 取得した行データ(7カラム)はTargetExist(構造体変数)に格納 |
右上

構造体のままだと扱いづらいので、配列型の変数に格納していく処理
構造体のまま扱う方法を知っていれば必要がないのですが…
① TargetExist(構造体変数)の構造体ピンを分割(integer型の7配列)
② ArrayExist(integer型の配列変数)に対しAddで配列追加していく
③ TargetPoint(構造体変数)の構造体ピンを分割(vector型の7配列)
④ ArrayVec(vector型の配列変数)に対しAddで配列追加していく
下部

For Loop | (横配置)7列分のループ |
Get (a copy) Set Current Vec | ArrayVec配列の1番目をCurrent Vec(vector型変数)に格納 |
Get (a copy) Set Current Exist | ArrayExist配列の1番目をCurrent Exist(int型変数)に格納 Current Existには0,1,2,3のどれかが格納される |
Switch on Int | Current Existの値により分岐 0:ブロックを配置しない 1:100点ブロックを配置 2:400点ブロックを配置 3:1000点ブロックを配置 |
Spawn Actor from Class | 選択されたブロックをCurrent Vecの座標に生成 |
Remove Index | ArrayExistから最初のIndexを削除 ArrayVecから最初のIndexを削除 これにより格納済みの配列の1番目が繰り上がる |
エラーチェックなどは行っておらず、正しい形のDataTableが入力される前提です。


最後に
構造体に関しては、結局スマートに扱うことが出来ませんでした。
DataTableを使ったステージ生成は関数化して使いまわせれば便利だと思うのですが、結局構造体のピン分割による力業になってしまい、汎用性がなくなってしまったのは残念。
やり方はあると思うんですけどね…
次回、ステージセレクトとパッケージ化が出来たら「ブロック崩しを作ろう」シリーズは終了としたいと思います。
その後は、忘れない程度にUnrealEngineに触りながら積みゲー崩しに戻ろうかと…
でもUE触ってるとどんどんやりたいこと出来てくるし、触らなくなって忘れるのが怖いんですけど。
理想としては、自分で暇つぶしに遊べるスマホゲームが作りたい(笑)
コメント