2014年12月26日金曜日

やってはいけないCG制作の感想

やってはいけないCG制作 (ボーンデジタル)

読みました.
感想としては,これはアーティストだけでなくアーティストから素材を受け取る側も是非読んで欲しい一冊だな,と思いました.

内容としては,新人アーティストがやらかしてしまった色々を上司かつ教師役の方が修正方法などを教えていく対話形式になっています.会話のテンポが良いこともあって,非常にサクサクと読み進めることができました.

まず良いなと思ったのは,教師の高野さんが新人の守本さんに色々と説明をする際に,この説明だと分かってなさそうだな,と感じたら別の例えなどで説明する,という一連の流れがあることです.あっ,新人ってこういう勘違いしてたりするんだ,こう言い換えるのもありなのか,など色々と勉強になります.プログラマにしてみれば,アーティストに何らかの技術の説明をする場合の参考になります.

例えば,アーティストから受け取ったデータが上手く扱えない場合に,プログラムに問題があって扱えないのか,そもそもデータに問題があるのかを判断する必要があります.アーティストがやってしまいそうなミスを知っていれば,まずそれをチェックしてみる,という選択肢が増えます.

また,アーティストに修正を依頼する際も,具体的な修正方法を指定できれば,アーティストにあれこれ問題点を調べてもらって,クリエイティブな作業をする時間を削る,ということも減ります.
提出してもらうデータの指定をする際にも,少しでも具体的な指定が出せれば,やり直しを減らすことができます.

ボーンデジタルの訳書はお高いことが多いですが,この本は訳書ではなく2,100円(税抜き)とお買い得です.新人アーティストにそっと渡すのも良いかもしれません.もちろん,ベテランでも何でも知っているというわけではないので,後輩に教えるときに参考になりますよ,と言って渡したりして勘違いを修正してもらうのも良いかもしれません.

この本みたいに,やってはいけないプログラミング,みたいな本が出て欲しいところです.

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でトゥーンレンダリング(仮)です.