【Unreal Engine5】初めてのゲーム開発 <第15回> ブロック崩しを作ろう④

残り課題

今回 ブロックの造形(見た目を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倍にすることで各辺の長さが算定できます。

《調査結果》

対象XYZ
ターゲットブロックの大きさ480760320
フロア(BP_BaseBlock)の大きさ80006000100
※実際の戻り値(XYZ)はビューポートの向きに左右されるので、ワールドのXYZに対応するよう入れ替えて記載

ブロック配置設計

現在使用しているステージのフロアサイズは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 EventCreate Stageイベントの開始地点
For Loop4行分のループ
Get Data Table RowRow Nameをキーにデータテーブル(DT_BlockPoint)から行データを取得
Row Nameは0~3のname型(ここの処理の為にそうしてます)なのでIndex(0~3)を型変換してキーとして使用
Integer⇒string⇒nameと変換(直接変換はできなかった)
取得した行データ(7カラム)はTargetPoint(構造体変数)に格納
Get Data Table RowRow 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 IntCurrent Existの値により分岐
0:ブロックを配置しない
1:100点ブロックを配置
2:400点ブロックを配置
3:1000点ブロックを配置
Spawn Actor from Class選択されたブロックをCurrent Vecの座標に生成
Remove IndexArrayExistから最初のIndexを削除
ArrayVecから最初のIndexを削除
これにより格納済みの配列の1番目が繰り上がる

エラーチェックなどは行っておらず、正しい形のDataTableが入力される前提です。

最後に

構造体に関しては、結局スマートに扱うことが出来ませんでした。
DataTableを使ったステージ生成は関数化して使いまわせれば便利だと思うのですが、結局構造体のピン分割による力業になってしまい、汎用性がなくなってしまったのは残念。

やり方はあると思うんですけどね…

次回、ステージセレクトとパッケージ化が出来たら「ブロック崩しを作ろう」シリーズは終了としたいと思います。

その後は、忘れない程度にUnrealEngineに触りながら積みゲー崩しに戻ろうかと…
でもUE触ってるとどんどんやりたいこと出来てくるし、触らなくなって忘れるのが怖いんですけど。

理想としては、自分で暇つぶしに遊べるスマホゲームが作りたい(笑)

コメント

コメントする

目次