2014年12月12日金曜日

UMGで電卓を作る

この記事は,Unreal Engine 4 Advent Calendar 2014の12日目の記事です.
昨日の記事は,@aizen76さんのUE4で使えるプラグインいろいろでした.

先週の記事では,UMGのレイアウト用ウィジェットを紹介しました.
今日は実践編として,UMGを使って電卓を作ってみます.なお,UE4のバージョンは4.6となっています.

まず,適当なプロジェクトを作って,UMGのブループリントを追加します.コンテンツブラウザ上で右クリックメニューを開き,ユーザーインターフェースからWidgetブループリントを選びます.名前はとりあえずCalcとしておきましょう.

いったん解説に使う予定の画像だけ掲載します.この画像を見るだけでも何となく電卓は作れるかもしれません.
間に合えば今晩に解説を載せます.

間に合いませんでしたが,解説はちゃんと書きます.細かいことは画像の中に書いてたりするので,画像の方を参照してください.なお,ブループリントの基本は理解しているものとして話を進めます.

コンテンツブラウザを右クリックし,ユーザーインターフェースからWidgetブループリントを追加します.


メニューのブループリントの横の三角からレベルブループリントを開き,ゲーム開始時にウィジェットが表示されるようにします.


レベルブループリントに書き込む内容は,次の図のようにCreate Widgetノードとadd To Viewportノードです.


先ほど追加したWidgetブループリントをダブルクリックし,まずはデザインを決定します.電卓はマス目状にボタンを配置すればできるので,Grid Panelを利用します.ルートのCanvas Panelを削除して,Grid Panelを配置します.


Grid Panelを配置したら,詳細から4列(Column)と5行(Row)を追加します.追加した行や列の重みは1にしておいて,均等な幅になるようにします.

列と行の追加ができたら,ボタン(共通の中のButton)を配置していきます.ボタンの中にはテキストを追加して,それぞれの数字や演算子(+,-,/,*,=)を入力します.最後に,結果表示用のテキストを一番上に配置します.



デザインが終わったら,グラフエディタに移り,変数タイプIntegerの変数resultを追加します.この変数には,計算結果を格納します.


変数を追加したらコンパイルしておきましょう.


コンパイルが終わったらデザイナに戻り,結果表示用のテキストを選びます.テキストの表示内容として,先ほど追加したresultを読み取るように,プロパティバインドを作成します.


バインドを作成するとグラフエディタに移るので,単純にマイブループリントからresultを引っ張ってきて,取得するようにし,resultをReturn Valueにつなぎます.


この時点で実行してみると,見た目はそれっぽくなります.


では,まずは数を入力できるようにします.数字のボタンを選択し,詳細の下の方からAdd OnClickedを押しましょう.


グラフエディタに移り,OnClicked(ボタン名)が表示されていると思います.電卓の挙動を見てみると,数字のボタンを押す度に右側に数字が追加されていきます.これは,resultに入っている値を10倍して押したボタンに対応する数を足した値をresultに設定することと同じです.これを書いたのが次のブループリントになります.


まずは0のボタンで作ってみました.次は1のボタンを押した場合を作ってみましょう.


上の図の赤で囲った部分以外違いがありません.同じような処理を2度作った場合,関数やマクロにすることを検討しましょう.今回は,関数化しておきます.マイブループリントから関数追加を選び,Add Valueという名前を付けます.


関数を作った場合,何か入力が必要な場合は自分で追加する必要があります.この場合,どのボタンを押したのか,という情報が必要なので,外からvalueという名前で入力できるようにします.後は,最初に0のボタンを押した場合に作ったブループリントと同じになります.

これを全ての数字のボタンに適用すると,次のようなブループリントになります.


この時点で画面にウィジェットを表示させて数字のボタンを押すと,電卓のように数字が表示されます.ただし,扱える数値の上限を超えている場合の処理が無いので,途中から変な数値に変わっていきます.

さて,ここからが本番です.電卓なので,ちゃんと足し算やかけ算ができるようにしていきます.電卓の挙動を見てみると,演算子(+や-など)を押した後,次の数字を押すまでは前に入力した値が表示され,数字のボタンを押した瞬間に新しい値に表示が変わります.つまり,演算子ボタンを押した後に数字のボタンを押したかどうかを覚えておく必要があります.また,ある演算子ボタンを押した後に数値を入力し,再度何かの演算子ボタンを押すと,計算が実行されます.そのため,直前に押されている演算子ボタンが何かといった情報が必要です.

そこで,次のような変数を追加します.

mode (Integer)
直前に押した演算子ボタンの種類を覚えておくための場所です.
stack (Integer)
途中までの計算結果を保存しておく場所です.
stackUsed (Boolean)
stackに何か格納しているかを表します.何か値が入っているならtrue,入っていなければfalseになります.
digitPushed (Boolean)
数字のボタンを押したかどうかを表します.何かしらのイベント後に一度でも数字のボタンを押していればtrueになります.


追加した変数を組み込んでいきます.まず,Add Value関数の中で,数字を押した後には必ずdigitPushedがtrueになるように,digitPushedの設定ノードを組み込みます.


結果を表示するためのテキストのプロパティバインドに使っている関数は,次のように変更します.
まず,resultだけでなくstackの結果も取得し,Select Intノードを使ってどちらかを選んだ上でReturn Valueにつなぐようにします.


選択の条件は,スタックに何か入っていて,数字ボタンを押していない場合にstackを選ぶことなので,そのようにstackUsedとdigitPushedを取得して,上記を参考にノードをつないでいきます.NOTは否定用のノードで,digitPushedに対してNOTを使うと,ボタンを押していない時にtrueになり,ボタンを押した後はfalseになります.

ANDノードは,入力の両方がtrueの場合にtrue,それ以外の場合はfalseになるので,stackUsedかつdigitPushedではない,という条件ができあがります.あとは,ANDの結果をSelect Intノードにつなぎます.

ここまできたらあと一息です.最後に,modeに合わせてstackの内容などを更新するUpdate By Mode関数を追加します.

まず,modeの値によって条件分岐をするため,モードがどの数値かを判定する処理を作ります.
modeを取得し,Equalノードで値を比較します.


  • 0は何も押していない状態
  • 1は+を押した状態
  • 2は-を押した状態
  • 3は*を押した状態
  • 4は/を押した状態

まず,何も押していない状態の場合,resultの値をstackに退避させます.



次は,+が押されている場合と-が押されている場合です.それぞれ,stackの値とresultの値を+ノードで足したり,-ノードで引いたりして,結果をstackに戻します.-の場合,stack - resultとresult - stackは結果が違うので,ノードをつなぐ順番に注意しましょう.


最後は,* (かけ算)と/(割り算)です.こちらも処理は+や/と変わりませんが,割り算は順序に気をつけましょう.


最後に,それぞれの計算結果をstackに設定した後に,stackUsedをtrueにし,resultを0に再設定し,digitPushedをfalseにする共通の終了処理につなぎます.


デザイナでそれぞれの演算子ボタンから,Add OnClickedでイベントを追加し,以下の図のようにUpdate By Modeを呼び出した後にmodeを適宜設定するようにノードをつなぎます.


最後に,=を押した場合,stackに何かしらデータが入っていれば,Update By Modeを呼び出して,計算などを終わらせておき,stackの値をresultに戻し,stack,stackUsed,modeをリセットするようにします.

これで,電卓はいったん完成です.実行して,簡単な計算をしてみましょう.

正直なところ,電卓なんて簡単だろう,と思っていたのですが,結構色々と考えることがあって,ちゃんと作るとなると結構面倒でした.UMGの実践例としてはあまり良くなかったかな,という気もするのですが,無駄にハイスペックを要求する単なる電卓,という誘惑には勝てませんでした.

ここで作った電卓はあくまでも簡易的なものなので,もっとUMGを弄って色々な機能を追加してみてください.


明日というか今日は,@monsho1977さんで,何かしらネタになるマテリアルを作るそうです.
楽しみですね.

2014年12月6日土曜日

UMG(Unreal Motion Graphics)でのレイアウト用ウィジェットの紹介

この記事はUnreal Engine 4 Advent Calendarの6日目の記事です.

昨日は@s_ssk13さんのリダイレクター ~消えないゴミファイルの謎~でした.

UMG(Unreal Motion Graphics)は,タイトルメニューやオプション画面などUIを実装するための機能です.基本的な使い方は,公式ドキュメントのUMG UI デザイナのクイックスタートガイド3D ウィジェットの作成 (4.6からの実験的機能)を読みながら手を動かせば,何となくつかめると思います.

しかし,画面に配置できるコンポーネントについてはリファレンス(公式ドキュメント)があるものの,何ができるかが書いてあるだけで,どう設定すれば書いてあることが実現できるかについてはあまり情報がありません.この記事では,UMGのレイアウト用コンポーネントの挙動について解説します.なお,この挙動は実験的に推察したものであり,コードを詳細に確認したものではないので,何か間違いがあればご指摘ください.

Grid Panel

Grid Panelは,表示範囲を指定した数の行と列に分割し,それぞれのマスに子ウィジェットを配置することができます.


行と列の数は,図のようにGrid Panelの詳細のFill Rulesで設定します.Column Fillの+を押すと列が増え,Row Fillの+を押すと行が増えていきます.Column FillやRow Fillの左の三角を押すと,それぞれの行や列の幅の重みを指定できます.上の図では,列それぞれの重みを1にしてあるので,配置したボタンウィジェットは,ちょうど左半分を埋めるようになっています.同様に,1列目を2,2列目を1にした場合,下の図のように1列目に配置したボタンウィジェットは3分の2を占めるようになります.


つまり,それぞれの列や行のサイズは,(列の重みの合計)分の(ある列の重み)の幅を持つようになっています.


Grid Panelに配置した子ウィジェットには,自動的にGrid Slotが追加されます.Grid Slotでは,次のような設定ができます.

Row
何行目に配置するかを示す.0行目,1行目と0から始まるので注意すること.
Column
何列目に配置するかを示す.0列目,1列目と0から始まるので注意すること.
Row Span,Column Span
何行,または何列を利用するかを示す.たとえば,上の図のようにRow Spanを2にすると,2行分を使った表示になる.

また,配置する行や列の変更は,子ウィジェットを選んだときに現れる上下左右の矢印をクリックすることでも変更可能です.

Uniform Grid Panel


Uniform Grid Panelは,Grid Panelと同様に表示範囲をいくつかの行と列に分割し,それぞれの子ウィジェットを配置することができます.Grid Panelではそれぞれの列や行のサイズを自由に変更できましたが,Uniform Grid Panelでは配置した子ウィジェットの設定で列や行の幅が変わります.


図のようにUniform Grid Panelの子ウィジェットには,自動的にUniform Grid Slotが追加されます.RowやColumnの意味はGrid Panelの子ウィジェットの時と同じですが,Uniform Grid Panelの場合,子ウィジェットのRowやColumnの最大値を使って表示範囲を分割するようになっています.たとえば,上の図の場合,それぞれのボタンのColumnが0,1,2となっているため,均等な幅の列が3つできています.あくまでも最大値なので,たとえばColumnが0の子ウィジェットと9の子ウィジェットがあったとすると,列は10分割されることになります.

公式のリファレンスにも書いてありますが,アイテム選択画面などで利用できそうです.

Horizontal Box,Vertical Box

Horizontal Boxは,子ウィジェットを横方向に配置していくことができます.Vertical Boxは,子ウィジェットを縦方向に配置していくことができます.


Horizontal Boxに配置した子ウィジェットには,自動的にHorizontal Box Slotが追加されます.Vertical Boxの場合は,Vertical Box Slotが追加されます.ここで重要になるのが,Sizeの設定です.

自動 (Auto)
表示に最低限必要なサイズになります.
塗りつぶし (Fill)
自動が設定されている子ウィジェット全てで使われるサイズを引いた残りの部分をから,設定されている重みに合わせてサイズを割り振ります.

塗りつぶしが少し分かりにくいので,もう少し詳しく説明します.自動を選んでいると,上の図のようにテキストボックスを子として持っているとその分だけ幅が広がり,無い場合はボタンの必要最低限の幅を取るようになります.Horizontal Boxの幅が10として,自動になっている子ウィジェットの幅の合計が4とすると,残りは6になります.塗りつぶしになっている子ウィジェットは,この6を割り当てられた重みに従って分割しているようです.この重みは,塗りつぶしを選ぶとその右側に入力ボックスがでるはずなのですが,どうもこの記事を書いている時点では日本語版では表示されないようになっているようです.そのため,デフォルト値の1が入っており,均等に分割されるようになっています.


上の図のように,英語版にすると重みの入力用のボックスがFillの右側に表示されます.

Canvas Box

Canvas Boxでは,子ウィジェットに対してアンカーを設定し,そのアンカーからの相対位置で子ウィジェットの位置を決めることができます.
アンカーについては,公式ドキュメントに詳しい説明が追加されていたので,そちらを参照してください.

まとめ

今回は,UMGのレイアウトシステムから,Grid Panel,Uniform Grid Panel,Horizontal Box,Vertical Box,Canvas Boxを紹介しました.他にもいくつかレイアウト用のウィジェットはあるのですが,そちらについてはまだあまり試せていないので,そのうち何か書けたらな,と思います.

UMGは,最初からマルチプラットフォームを考慮して作られているだけあって,様々な解像度でUIが作れるようになっており,解像度の違いを吸収するための機能も用意されています.そのため,ゲームを作るためだけでなく,他のツールなどを作る場合にも使えるのではないか,と考えています.皆さんも是非使ってみてください.

明日は,@hima_zinnさんのUE4でトゥーンレンダリング(仮)です.

2014年11月25日火曜日

逆行列を求める手順

たまにオレオレ行列ライブラリを作りたくなり,逆行列を求める手順を書くところで公式が長くて忘れていて調べ回る,ということをしているので作り方をメモしておく.

ある行Rとある列Cを取り除いた行列の行列式に(-1)の(R+C)乗を掛けたものを余因子と言う.

ある行またはある列の要素全てについて,余因子を求めて足し合わせると行列式が求まる.よって,これを1次正方行列になるまで繰り返せば,行列式を求める手順が分かる.

行列式が0でない場合,逆行列が作れて,行R列Cの要素は余因子で,最後に全ての要素に行列式の逆数を掛ければ良い.

2014年11月19日水曜日

UE4で作ったものをOculus Rift DK2で見るまで

Oculus Rift DK2が届いたので,さっそくUE4で作ったものを見れるようにしてみよう,と思ったものの,いろいろ引っかかったので手順をまとめておく.


  • OS - Windows 8.1 Pro
  • CPU - Intel Core i7 4710MQ
  • GPU - GeForce GTX 860M version 9.18.13.4475
  • UE4 - UE4.5.1

まず,Oculusの公式サイトの右上のデベロッパから開発者向けサイトに移動する.


Downloadsタブを選び,0.4.2 betaからWindows Runtimeをダウンロードし,インストールする.注意したいのが,2014/11時点で0.4.3のRuntimeをインストールすると,UE4が立ち上がらなくなる場合があるなど問題が起こることがあるので,0.4.2を選ぶこと.


インストールが終わり,接続も済んだら,今度はディスプレイの設定を変更する.コントロールパネルを開き,デスクトップのカスタマイズを選ぶ.


ディスプレイを選ぶ.


左のメニューから,セカンドディスプレイに表示,を選ぶ.


拡張を選ぶ.どうも拡張を選んでおかないと,PCのディスプレイの解像度によっては上手く動かなくなるらしい.


左メニューの解像度の調整を選び,セカンダリディスプレイ(2と表示されている)になっているDK2を選び,向きを横(反対向き)にする.


適当なUE4のプロジェクトを開き,プレイボタンの右側の小さい三角をクリックしてメニューを開き,スタンドアローンゲームを選択する.


起動後,Alt+Enterを押してOculus Riftに表示されれば成功.ただし,時折失敗する場合があり,その場合はShift + Windowsキー + 右でウィンドウをOculus側に移動させ,改めてAlt + Enterを押すと表示される.

終わる場合は,再度Alt + Enterを押して通常画面に戻し,Shift + F1でUE4ゲームのマウス操作モードを抜け,右上の×ボタンを押せば良い.

Shift + Windowsキー + 右でウィンドウを移動させた場合,Shift + Windowsキー + 左でウィンドウを元のディスプレイに戻すなど必要かもしれない.

2014年10月17日金曜日

UMGのプロパティバインディングとスライダーを使ってみた

UMGのブループリントに変数を追加し,UMGのコンポーネントと連動させることができるようなので,それを利用してテキストボックスとスライダーを連動させてみた.

Widgetブループリントの生成


ここでは,SampleWidgetBPというWidgetブループリントを作成し,Editable Text BoxとSliderを配置し,それぞれValueTextとValueSliderという名前にしてみた.

変数の追加


次に,グラフからプロパティとして利用するFloatの変数Valueを追加しておく.

ValueTextのテキストの取得と設定に関する設定

まず,テキストボックスに変数Valueの値を取得して変換して設定するようにする.


更に,テキストボックスが編集された場合にValueに値を設定し,Sliderの値も変更するようにする.(Sliderには設定しなくてもできる気もする)



ValueSliderの値の取得と設定


ValueTextと同様に,詳細のValueを変数Valueを参照するようにしたり,値が変化した際にValueに設定するようにしている.




Widgetの表示


最後に,レベルブループリントなどからWidgetを生成して,Add to Viewportで画面に出せば,Sliderの変化に合わせてテキストボックスの値が変わり,テキストボックスの変更に合わせてスライダーが移動するUIが完成する.


最後に

SliderにプロパティとしてValueを設定しているところをバインディングに変更すれば,Sliderに値を設定する部分は不要かもしれないが・・・眠いのでまた明日にしよう.

2014年10月15日水曜日

Unreal Motion Graphics (UMG)でプログレスバーを表示してみた

UMGでプログレスバーを作ってみました.

UMGを有効にするには,メニューの編集からエディタの設定を選びます.

実験的,の項目からUMGにチェックを入れ,エディタを再起動します

コンテンツブラウザから新規のアセットを追加します.右クリックメニューからユーザーインターフェースの中のWidgetブループリントを選びます.

できたブループリントのファイルをダブルクリックして開くと,UMGのエディタになるので,適当にプログレスバーを配置し,名前をProgressに変更しておきます.終わったらコンパイルしておきます.

レベルブループリントを開き,追加したブループリントの名前のオブジェクトの変数を作ります.(この図では手抜きでデフォルトの名前のまま).そして,Begin Playイベント時にCreateWidgetを利用して作成したWidgetを生成します.CreateWidgetに作成したブループリントを指定すると,Widgetが生成できます.CreateWidgetが返すのはUserWidget型のオブジェクトなので,キャストを挟んで変数に設定します.

このWidgetから線をひっぱり,Add to Viewportを呼び出すと,画面に表示されます.

Progressと名付けたfloat型の変数を追加しておき,Begin Playイベント時に0で初期化しておきます.

Tickイベントで毎フレーム0.001ずつProgressの値を増やします.ただし,100を超えないようにします.

最後に,Widget変数から線をひっぱりGet Progressと打つと,プログレスバーのオブジェクトが取得できます.そこから更に線をひっぱると,Set Percentというものがあるので,そこに変数Progressの値を設定します.

これをコンパイルして再生すると,プログレスバーが徐々に進んでいきます.

他のUIもいろいろ触ってみたくなってきました.