みつまめ杏仁

アンリアルエンジン(UE4)でGUIを作るためにゴニョゴニョしてます。UIデザイナーの皆様の助けになれば幸いです。

キャラセレを作ってみる サムネイルを並べる

どうもです。まだ続いてますよ~。

あまり間が開かないようにしたいのですが、なかなか時間がとれなくてペースが悪いですが頑張って更新していきます。UE4でUIを作ることになった初心者の方向けに、オペレーションを幾分丁寧に書いてるのもありますが、そろそろ扱いに慣れてきている頃合いだと思うのでスピード上げていきたいと思います。

サムネイルを並べる前に、いったん過去記事のリンクを並べておきます。

タイトル名がいつの間にか変わっていたのに気づいて修正しました。

  1. キャラセレを作ってみる 素材編
  2. キャラセレを作ってみる 背景編
  3. キャラセレを作ってみる サムネイル編
  4. キャラセレを作ってみる サムネイル編2

今回サムネイルを画面に並べるところを作ります。

コンテンツブラウザを見ると、WidgetBlueprintアセットが2つあります。2回目の記事で背景を置いたWidgetを編集します。

 

Wrapボックスを使ってみる

編集モードをDesignerに切り替えて、キャンバスにWrap Box(ラップボックス)をドロップします。

Wrap BoxはPaletteタブのPanelカテゴリの中にあります。

f:id:hiyokosabrey:20170610234443p:plain

f:id:hiyokosabrey:20170610234656p:plain

キャンバスの中で大体の位置を決めたら、設定を変更します。

f:id:hiyokosabrey:20170610235219p:plain

 サイズは、256x256のサムネイルが4つ横に並ぶので1024、縦に2つ並ぶので512にしています。

この WrapBoxはブループリントから触るので、isVariableチェックボックスにチェックを付けます。名前は適当で構わないですが、ブループリントで扱う場合パーツの種類で動作や扱えるノードが変わってくるので、なるべくアンダーバーより前は名前を残すことをおすすめします。なので、上の画像だと、「164」 の部分をリネームする感じです。

ちなみに isVariable にチェックを付けるとキャンバスに置いているパーツのリストが変化します。

f:id:hiyokosabrey:20170611000757p:plain

 ブラケット[ ]が外れます。小さな変化ですが、知っておくと後で以外に役立ちますよ。

 

 

これでキャンバスの準備は完了です。

編集モードをGraph に切り替えます。

 

Initialize関数を作る

イニシャライズと読みます。役割はこれから仕事をするための準備をするところです。機能の多いものを作ろうとすると、何かと下ごしらが必要になります。UIを作っていると後から機能が増えたりすることはよくあることで、準備するものもまた後から増えることになります。なくても何の問題もないですがオススメしたいので作っていきます。

まず関数を新しく追加します。名前は Initialize とか Init でOK。

f:id:hiyokosabrey:20170611002547p:plain

次にサムネイルの並びを設定する配列変数を新しく追加します。

配列変数は VriableType のプルダウンメニュー右側にあるアイコンをクリックして切り替えることで簡単に変更できます。

f:id:hiyokosabrey:20170611003147p:plain

f:id:hiyokosabrey:20170611003852p:plain

 

キャラクターはID番号を振って管理するのが一般的です。

分かりやすく0~7の整数で管理したいので、Integer型で用意します。

できた配列変数をさっきのInitialize関数の中に Set でドロップしてつなぎます。

f:id:hiyokosabrey:20170611004843p:plain

左右に四角いピンがあります。値を入力したいので、左のピンからドラッグして、Make Array ノードを取り出します。

f:id:hiyokosabrey:20170611005145p:plain

取り出せたら、Add pin + をクリックして[7]まで増やします。

f:id:hiyokosabrey:20170611005430p:plain

こうなります↓

f:id:hiyokosabrey:20170611005756p:plain

値が全部 0 になっているので、ここにキャラの番号を入れていきます。

サムネイルのテクスチャは ↓ のように並んでいるので、f:id:hiyokosabrey:20170611004639p:plain

数字が重複しないように入力します。順番はお好みで。

 

0~7を入力し終わったら、関数はいったん編集完了です。

EventGraph に戻ります。

f:id:hiyokosabrey:20170611010533p:plain

Event Construct という赤いイベントノードに、できたてのInitialize関数をつないでやります。

f:id:hiyokosabrey:20170611010723p:plain

よくみたら、関数のノードなのにイベントと同じアイコンになってます。ちょっと難しくなるのですが、関数は仕事をしたら結果や成果を報告することができます。戻り値とか言うとプログラマっぽくなりますね。ノードの右につく出力ピンにあたります。それがあればfのアイコン。なければイベントのアイコンになります。

 

 WrapBoxにサムネイルを追加する

次にいよいよサムネイルを並べる関数を作ります。

f:id:hiyokosabrey:20170611013048p:plain

ここに For Each Loop ノードをつなぎます。(キーボードの F を押しながらクリック)さらに先に作っておいた配列変数をGetで取り出して ForEachLoopノードにつないでやります。

f:id:hiyokosabrey:20170611013429p:plain

この「ふぉーいーち」ノードは配列変数のために用意されているノードで、配列変数に仕込まれた値のぶんだけ回しますよ。という働きをします。今回用意した配列変数は [0]~[7]まで値が入っているので、8回だけ回してくれます。ここでいう「回す」というのは、右上の LoopBody と書かれた実行ピンの先につながっているものが対象です。配列変数の中身の分だけ回すと、右下のComplete のピンから出てきます。

 

次にCreate Widgetノードを取り出して、Loop Body の実行ピンにつなぎます。

f:id:hiyokosabrey:20170611145912p:plain

ノードのClassのところに、サムネイル用に用意したWidgetをセットしてやります。

セットしたら、CreateWidgetノードの右に ReturnValue ピンがあるので、このピンの上で右クリック 、メニューから Promote to Variable を選択します。

f:id:hiyokosabrey:20170611201817p:plain

新しく変数が作られるので、

f:id:hiyokosabrey:20170611201854p:plain

これをいったんグラフから削除(Deleteキー)します。

消しても左のVariableタブの中にはちゃんと残っているので、これを配列型に切り替えます。名前も変えておきます。WD_Buttonsにしました。

改めてこの配列を Get でグラフにドロップします。

f:id:hiyokosabrey:20170611201842p:plain

この配列は空っぽです。そこでForEachLoopで8回CreateWidgetした結果(ReturnValue)を配列に追加するのでAddノードをつなぎます。Addノードは配列専用のノードで配列変数からドラッグして探すとすぐに見つかります。

f:id:hiyokosabrey:20170611202133p:plain

この配列は、後から個別にサムネイルのボタンを制御するために利用します。

 

いよいよ WrapBox に追加します。

isVariable のチェックを付けると、Variableリストの中に、WrapBoxが変数として存在するようになるので、これをグラフに Get でドロップします。

ドロップしたら、そこから Add Child Wrap Box ノードを取り出して下図のようにつなぎます。

f:id:hiyokosabrey:20170611203027p:plain

さらに、サムネイルを作ったときに用意したセットアップ用の関数を取り出してつなぎます。この関数は、サムネイルのWidget内にしか存在しないので、ReturnValueからドラッグした場合だけ検索できます。

f:id:hiyokosabrey:20170611205533p:plain

f:id:hiyokosabrey:20170611205157p:plain

この関数にはパラメータ(引数)を渡せるように作っていました。

f:id:hiyokosabrey:20170611210147p:plain

なので、ピンに値を渡せるようにつなぎます。

f:id:hiyokosabrey:20170611210459p:plain

ForEachLoopから出てくる値は2つあります。

Array Element は、 配列の中身(Initialize関数で Make Array で仕込んだ中身)

Array Index は、順番(0~)

まだパラメータのピンが残ってますが、早く表示してみたいので、次に進みます。

これで、WidgetがCreateされて、作ったそばから配列に積んでいって、WrapBoxに子供として追加して、最後にサムネイルの関数に必要な値を渡す仕事が1セット。合計8セット行われるようにできました。

この仕事が終わったらサムネイルの出現用のアニメーションを呼びたいので、下図のようにつなぎます。

f:id:hiyokosabrey:20170611211727p:plain

Completedのピンから、また次のForEachLoopをつないで、サムネイルの中のReady関数をつないでやります。仕上げにReturnノードをつないでおきます。

だいたいできました。

ここで、EventGraphに戻って、この関数をつなぎます。

f:id:hiyokosabrey:20170611212441p:plain

 

f:id:hiyokosabrey:20170611212452p:plain

 

これでコンパイルして保存します。

 

レベルを用意する

Widgetを表示するためには、レベルを用意する必要があります。レベルはコンテンツブラウザから作成します。

f:id:hiyokosabrey:20170611220802p:plain

適当に名前を付けたら、ダブルクリックします。

レベルを開くとビューポートの右下が変化します。下は”Select”という名前のレベルを作った場合。

f:id:hiyokosabrey:20170611221421p:plain

 Persistant というのは今編集対象のレベルを意味しています。

ここが切り替わったのを確認したら、レベルブループリントを編集します。

レベルブループリントの編集方法は少し変わっていてエディタの Blueprints ボタンの右にある小さな▼をクリックしたらコンテキストメニューが出てくるので、この中からOpen Level Blueprint を選びます。

f:id:hiyokosabrey:20170611221837p:plain

グラフエディタが開いたら、Event BeginPlay ノードに Create Widget ノードと、Add to Viewport ノードをつなぎます。

f:id:hiyokosabrey:20170611222534p:plain

CreateWidgetノードの、Class のところは、今回作ったメインのWidgetをセットします。

コンパイルして保存しておきます。レベルは保存の方法も少し変わっています。ビューポートの上にあるSave Current ボタンから保存します。

f:id:hiyokosabrey:20170611222951p:plain

レベルが用意できたので、さっそくPlayしてみましょう。

保存の時と同じくビューポートの上にあるPlayボタンをクリックします。

うまく表示されるでしょうか?

f:id:hiyokosabrey:20170611223459j:plain

おや? いつまで経ってもサムネイルが表示されません。Escキーを押して再生を止めます。

わざとらしいことしてごめんなさい。原因はサムネイルWidgetに仕込んだ Set Timer by Event ノードです。このノードは数値を受け取ると、受け取った時間だけ待機してその後つながったイベントを実行します。 実は 0 を渡すと仕事をしなくなるのです。

f:id:hiyokosabrey:20170611224330p:plain

気を取り直して、先ほどの関数を編集します。

サムネイルのSetupButton関数に0以外の数値を入れて再生してみましょう。

f:id:hiyokosabrey:20170611224801p:plain

コンパイルしてエラーがないのを確認したら保存してPlay・・・

f:id:hiyokosabrey:20170611225109j:plain

ようやく表示されました。

ただ一斉に出てきて面白くないので一工夫します。このままだと、わざわざDelayTime入れた甲斐もないです。

ふたたびさっきの関数を編集します。

まずローカル変数を用意します。左のMyBlueprintタブの中に Local Variables  というカテゴリがあるので、そこに追加します。

f:id:hiyokosabrey:20170611225641p:plain

DelayTimeは小数点で扱うのでFloat型です。ちなみにTempというのは「テンポラリ」の略で、「一時的な」という意味でよく使われます。このローカル変数はこの関数内だけで活躍します。関数の外には一切出ていけず一生をここで過ごします。さらに関数が仕事を終えるとこのローカル変数はメモリから破棄されて消えてしまいます。

実はそこがメリットだったりします。

で、さっそくつないでいきます。ローカル変数とはいえ扱い方は普通の変数とまったく同じです。グラフに ドロップして使います。

GetとSet の2タイプ をドロップします。

f:id:hiyokosabrey:20170611230928p:plain

間にFloat 同士の足し算 をするノードを挟みます。

f:id:hiyokosabrey:20170611230727p:plain

慣れないと解りにくいかもですが、

まず自分の値をGetして、そこに値を足して、自分自身の値を更新(Set)しています。

この処理を、Add Child Wrap Box の後に 瞬間的に行います。そしてすぐその値を渡しています。

足し算は適当にいろいろな数値で試してみてください。ちなみに 1.0 は1秒と同じ長さです。

これで完成です。

コンパイルして保存したら、再びPlayして確認してみましょう。

 

f:id:hiyokosabrey:20170611232253j:plain

しゅるしゅる~

f:id:hiyokosabrey:20170611232314j:plain

f:id:hiyokosabrey:20170611232326j:plain

やった。うまくいきました。

やっぱりこういうインタラクションがあるのと無いのとでは印象が変わってきます。さらに視線誘導にも役立ちます。

 

今回はここまでにします。

なかなかのボリュームになってしまいました。

サムネイルも表示できたので、次回はカーソルの登場です。

ではではステキなサムネライフを!