テンプレ通りのゲーム制作 FPS④ゲーム中の文字の表示
UIの作成
今回はゲーム中の文字の表示をやっていきます。このゲーム画面に表示される文字やアイコンの事をUI(ユーザーインターフェース)と言います。スコアや残弾表示、HPバーの表示などをやっていきます。前回の記事は以下の通りです。
UnrealEngineにはUIの作り方として以下の2種類があります。
- UMG(Unreal Motion Graphics)を使う
- HUD(Head Up Display)を使う
HUDの方はどちらかというとロックオンマークなどのリアルタイムに画面上に座標を変えて映すのに向いている手法なのですが、ちょっと扱うのには難易度高めなのでお手軽に文字が表示できるUMGの方を今回は扱います。
フォントの準備
まずはフォントの準備をします。UnrealEngineで使えるフォントはTrueTypeフォントとOpenTypeフォントです。Windows標準のフォントでも良いですが、折角なのでフリーフォントを使ってみましょう。今回は「源真ゴシック」というフォントを使っています。使用上の注意、特にライセンスと著作権についての部分はよく読んでおいてください。
源真ゴシック
http://jikasei.me/font/genshin/#_7
フォントファイルが用意出来たらコンテンツ直下にFontフォルダを作ってドラグアンドドロップしてインポートします。
このメッセージがでたらすべて「はい」で構いません
ウィジェットの作成
まずはUIの入れ物となるウィジェットを作っていきましょう。先ほどと同じくコンテンツ直下にUIフォルダを作り、その中で右クリックします。ユーザーインターフェース/ウィジェットブループリントを選びます。名前は「UI_Bullet」にします。
ユーザーウィジェットを選びます。
作ったウィジェットブループリントをダブルクリックして開きます。左側のパレットからパネル/キャンバスパネルをドラッグアンドドロップして置きます。黄緑の枠が出来るはずなので今後この中に各種UIを配置していきます。
さらにキャンバスパネル左下あたりにパネル/サイズボックスをドラッグアンドドロップします。作ったサイズボックスの中にVerticalBoxひとつとHorizontalBoxふたつを左下の階層パネル利用してドラッグアンドドロップします。
サイズボックスをセーフゾーン左下に作る
VerticalBoxとHorizontalBoxを階層パネルで追加する
現在HorizontalBoxが二つあると思いますがそこに一般/テキストをドラッグアンドドロップしてそれぞれに重ねるように配置します。
テキストボックスをHorizontalBox内に配置
セーフティゾーン内のは以下のようになっているはずです。
テキストをクリックして表示を変更します。詳細パネルで文字の調整を行います。画像のように変更してください。
- Size:フィル
- Horizontal Alignment:水平方向中央揃え
- Vertical Alignment:垂直方向に塗りつぶし
- Text:「残弾」
- Color and Opacity:(カラーピッカーで黄色)
- Font Family:(源真フォントのいずれか)
- Size:60
- Size:フィル
- Horizontal Alignment:水平方向中央揃え
- Vertical Alignment:垂直方向に塗りつぶし
- Text:「99」
- Color and Opacity:(カラーピッカーで白色)
- Font Family:(源真フォントのいずれか)
- Size:100
文字の調整が終わると以下のようになっているはずです。サイズボックスを使って位置を調整してかまいません。調整が終わったらコンパイルして保存しておいてください。
画面にウィジェットブループリントを表示させる
では作成したウィジェットブループリントを画面に表示しましょう。メインのレベルに切り替えてレベルブループリントを開きます。
何もないところで右クリックして「Beginplay」と入力しEvent Beginplayノードを作ります。「Creatw…」と入力してCreate Widgetノードを作ります。作ったノードのクラスを先ほど作ったUI_Bulletにします。ゲーム画面の上にウィジェットを作りますがこれだけでは表示されません。
CreateWidgetの青い出力ピンからワイヤを伸ばし、AddViewPortノードを追加します。再生ボタンを押してみましょう。開始と同時にユーザーインターフェースが表示されたはずです。位置に不具合がある場合はウィジェットブループリントを修正してください。
ユーザーインターフェースが表示された!
変数とユーザーインターフェースをバインドさせる
文字は表示されましたが残弾が”99”のままです。99にしたのは最大表示桁数(今回は2ケタ)を確認するためです。これを内部の変数とバインド(リンク)させます。ウィジェットブループリントを開き、弾数の99の部分をクリックした状態で詳細パネルのText部分の右側、バインドのプルダウンを開き、バインディングを作成を選びます。エディタがグラフ作成(ブループリント作成)モードになります。元のデザイナーモードとは右上のボタンで切り替えることができます。デザイナーの方を押すと最初のエディタの状態になります。
残弾数を表示するためにBP_Weapon_Componentのブループリントを改良します。BP_Weapon_Componentは銃の発射に関するクラスであり、以前30発撃つと撃てなくなる仕組みを追加しました。撃った数はカウントしていますが、銃の発射上限値である装弾数は30と直接数値入力しています。これは「マジックナンバー」と言われ、柔軟性に欠けるプログラミングではあまり望ましくない状態ですので変数化しましょう。コンテンツ/FirstPerson/Blueprints/BP_Weapon_Componentを開きます。以前作ったイベントでIA_Shootの入力イベントを探します。左の”EventGraph”項目のイベント一覧からダブルクリックすると素早く見つけられます。入力イベントに現在のショットが30未満かどうか調べる部分があります。30と直接入力しているスロットのピンからワイヤを伸ばしPromote to variable(変数に昇格) を選びます。変数が作られますので選択して、F2キーを押して名前変更モードにして名前をGunCapacityにします。コンパイルしてデフォルト値が30になっているのを確認します。
銃の装弾数-現在発射した数=残弾数なので発射後にNumOfShotを足すノードの後に続いて以下のように組みます。GunCapacityからNumOfShotを引いています。
この計算結果をBP_FirstpersonCharacterに伝える必要がありますので受け取る変数をFirstpersonCharacter側に作っておきます。コンテンツ/FirstPerson/Blueprints/BP_FirstPersonCharacterにを開きます。左側のパネルでプラスボタンを押して変数を作り、名前を「NumOfBullet」にしてInteger型にします。
コンテンツ/FirstPerson/Blueprints/BP_Weapon_Componentに戻ります。ショットが呼ばれるたびに残弾の計算結果がBP_FirstpersonCharacterのNumOfBulletに送られるようにします。キャストとは他のクラスにアクセスする手法です。BP_FirstPersonCharacterにキャストしてそのクラスがもつNumOfBulletにアクセス、Setして計算結果を送っています。
BP_Weapon_ComponentからBP_FirstPersonCharacterに計算結果を送る仕組みが出来たら今度は、ウィジェットブループリントからこのゲームの主役であるBP_FirstPersonCharacterの変数を見に行きます。
最初から用意されているノードの下の方で右クリックしてCast To BP_FirstPersonCharacterノードを作ります。これを右クリックして純粋キャストに変更を選びます。純粋キャストに変更すると実行ピンが無くなってノードの実行順に関係なく値を出力するノードになります。
BP_FirstPersonCharacterの青い出力ピンからワイヤを出してNumOfBulletのGetノードを出します。キャストノードの前にもワイヤを出してGetPlayerPawnノードを作ります。最後にNumOfBulletの出力ピンをReturnValueノードへ返せば出力が出来ます。ReturnValueのピンはピンク色の文字列を受け付けるピンで、計算結果のInteger型とは合致しませんが、自動的に文字列に変換するノードが間に入ります。これでプログラムを走らせると残弾数が表示できたはずです!
残弾がバインドして表示された
残弾表示の問題点を解決する
残弾数が発射と同時に表示が更新皿ましたが問題があります。
- ゲーム開始時に装弾数が0になっている。
- リロードした瞬間に装弾数いっぱいの数になってない
ここを直していきましょう。
- ゲーム開始時に装弾数が0になっている。
こちらはゲーム開始時にUIの残り弾数を表示される99の部分にBP_FirstpersonPlayer内の変数であるNumOfBulletの値が代入されているのですがデフォルト値が変数作成時の0のままなのが原因です。
BP_FirstpersonPlayerのクラスBPを開きます。BeginPlayノードにフォーカスして最後に処理を追加していきましょう。装弾数の初期値の変数はBP_Weapon_Componentに設定しましたので、この中のGunCapacity変数にアクセスします。その値をBP_FirstpersonPlayerのNumOfBullet変数に代入します。これでプレイすれば残弾数の初期値は装弾数の値になるはずです。
- リロードした瞬間に装弾数いっぱいの数になってない
次にリロードしても残弾数が装弾数いっぱいにならないのはリロード時にもGunCapacityの値が代入されないからです。これはどこに処理を書けばいいでしょうか?これはBP_Weapon_ComponentのIA_Reloadの入力アクションに処理を追加すれば良さそうです。IA_Reloadの入力アクションの最後に処理を追加します。まず、BP_Weapon_Componentから見て表示される変数を持っているBP_FirstpersonPlayerは他のクラスになりますのでアクセスするためにキャストノードを作ります。キャストノードを右クリックして「純粋キャストに変更」してください。すると実行ピンがなくなり、画像のようになります。キャストノードのObjectピンにはGetPlayerPawnノードをつけてください。さらに、キャストノードの青ピンからワイヤを伸ばしてNumOfBulletのSetノードを作ります。次にいま編集しているBP_Weapon_Componentの左上のコンポーネントパネルからGunCapacityをドラッグアンドドロップします。そのピンからワイヤを伸ばしてNumOfBulletのSetノードにつなぎます。下記の画像のように組んでください。これでリロードと同時に残弾表示がMAXになるはずです。
これでスタート時やリロード時の残弾表示が正しくなりました。UI表示の基本が学べたかと思います。次はスコアやライフ表示をやっていきたいと思います。
Discussion