みつまめ杏仁

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

ぷちコン振り返り

暑さが少し和らいだ気がしなくもないですが、確実に日暮れが早くなっているので地軸の傾きを実感しています。

 

残念ながら紹介されるまでには至らなかったですが、先日応募した第14回ぷちコンの簡単な振り返りを書きます。

 

今回のぷちコンの参加は、あまり集中して時間が取れなかったのもあって見送る気でいたのですが、締め切り前告知をツイッターで見た直後にネタが降ってきて心残りもあったので、急いで作ってみた次第です。

f:id:hiyokosabrey:20200913003737j:plain

 


【第14回UE4ぷちコン作品】タイトル長いので省略

 

 夏休みといえば宿題。遊びたい誘惑を振り切ったと思いきや、すぐに切れる集中力。遅々として進まなかった苦い記憶がふっと思い出されたので、この集中力をタイマーにしつつ、逼迫した状況に抗うゲーム。というイメージが浮かびました。

 

RollingTemplate をベースにしています。

 

  • 見えてる範囲を狭くしたい
  • おやつ食べて回復したい
  • いろんな誘惑がステージに置いてあって近づくと集中力が激減する
  • 集中力がなくなってくると徐々に視界の周りがざわざわする
  • レイマンの動きで状況を説明。飽きさせない動きにしたい

 

というのを最初考えていましたが、さすがに期限が目前すぎて猶予がなかったのでできる範囲で作りました。

後からこちらの記事を読んで、 練度の違いを実感。

paviliondv7.hatenablog.com

トルク制御を知っていればもっといろいろできたかもしれない予感。

勉強勉強。

 

 

 

BPのつながりについて

参考になるかわかりませんが、作例としてBPの構成をご紹介。

 

f:id:hiyokosabrey:20200914194335p:plain


 

GameStateクラスが全体の進行管理を担って、適宜HUDへの指示をします。

UI周りはすべて HUDクラスに一任しています。

 

このスタイルが結構気に入ってます。GameState と HUD には、ちゃんと調べたことはないですが、ほとんどのブループリントからアクセスすることができるのが理由です。

 

f:id:hiyokosabrey:20200912142522p:plain

自分の作ったやつにキャスト(型変換)しないといけないですが、頻繁にアクセスするのがわかっている場合は、変数化しておくとノードのつながりがスッキリしてグラフが見やすくなります。

 

GameState は状況の変化を感知したり、タイマーを動かしたりしています。画面表示に更新が必要になると、この GameStateから HUD に用意したカスタムイベント経由で値を渡します。

HUD は 画面のWidgetたちをすべて管理するようにしているので、受け取った値を表示しているWidget に流します。

 

UI表示までが少し遠い印象ですが、値の流れるルートが把握しやすく、改造が楽だったり、デバッグしやすかったりします。

複数人で作る場合、HUD と Gametate とで分担がしやすいのではと思うのですがいかがでしょうね。

 

 

視界について

集中すると周りが見えなくなるのをイメージして、スコープを除くような感じにしたかったので、最初 UMGのブラーエフェクトパネルを使ってみたのですが、ボケ具合がイマイチだったので、メインカメラの DOF を有効にしました。

f:id:hiyokosabrey:20200912202714p:plain

UMGだとガウシアンな感じがしてちょっとエモくない。

f:id:hiyokosabrey:20200912202723p:plain

DOFだと絞り羽の形がエモい。

 

中央のはっきり見えている部分はレンダーターゲットテクスチャ。

キャプチャ用のカメラを、メインカメラの子供にアタッチ。

f:id:hiyokosabrey:20200912203316p:plain

画面中央だけでいいので、レンダーターゲット用テクスチャのサイズは大きいとメモリ消費が厳しいので1024x1024 。 1080p だと上下に若干届かないくらい。

あとはこのテクスチャをマテリアルで抜いてUMGで配置するだけ。

f:id:hiyokosabrey:20200913105045p:plain

 

集中度合いをみて視界の大きさを変動させたりしたかったけど時間がなくて断念。

 

集中力がなくなってくると徐々に画面にノイズが重なってくるようにした。

f:id:hiyokosabrey:20200912204556g:plain

 

 

レーダーについて

今回実装に一番悩んだ部分。

f:id:hiyokosabrey:20200912205512j:plain

表示位置の計算は、座標から角度を得る atan2 を使って、UMG上で三角関数使えば戻せるなと考えていたけど、問題なのはどうやって散らばったオブジェクトを把握するか。

レーダーに映るのは一番小さなBallのみで、大きいBallにぶつかって分解されることでスポーンする仕組み。結構数が増減するので配列に動的に積むのはやめたほうがよさそう。ということで、マップにセットした大きいBallから総スポーン数を割り出して、最初から全部を配列で管理することにした。

f:id:hiyokosabrey:20200912214240p:plain

マップには 大きいBallを宿題7科目分置いたので、7×32 = 224個

一番小さいBallがスポーンする際に固有のID番号を渡すようにして、プレイヤーが触れたらそのID番号をバックしてDestroyするようにした。表示のOn/Off はBoolean型の配列を同様に管理して、スポーンしたら true 、いなくなったら false にする。

これをアクターとGameState 間でやり取り。

GameStateは常にスポーンされてるアクターの座標とプレイヤーの座標から角度を計算してFloat型配列を更新し続けていて、レーダー表示用のWidgetは、その配列から角度を取り出して表示に使うという流れ。

 

f:id:hiyokosabrey:20200913102051p:plain

 

 atan2(アークタンジェント)関数を使うと、

f:id:hiyokosabrey:20200913102110p:plain

XY座標と原点を結ぶ直線の角度(=傾き)を計算してくれます。

 

f:id:hiyokosabrey:20200912224018j:plain

今度は角度と半径、2つの値から、サインコサインを使って原点からのXY座標を計算します。あとは画面表示の際のズレを補正してやるだけ。ここがそこそこ面倒だったりする。

 

このレーダーの実装でそれなりに遊べるようになったので良かった。

これがなかったら、ストレスが溜まるだけだったので正直応募を諦めていたと思う。

 

 

レイマンについて

ちゃんとモーションつけて再生したかったけど、さすがに にわかでサクッとできる気がしなかったので、ポーズだけつけてアニメーションアセットを作った。

指を一本一本曲げていくのは意外に楽しくて、手の形でもかなり表情というか感情を出せるということに改めて気づけたので、グレイマンのように顔がノッペラだとなおさらいい勉強になりそう。グレーマンを使ったグラビアコンテストなんかも面白いかもしれない。完全に日本だけのコミュニティしかウケないだろうけど。

 

撮影用のレベルを作ってそこで適当にライトを置いて、解像度キャプチャーツールで撮ってテクスチャにしました。

 

 f:id:hiyokosabrey:20200913005337p:plain f:id:hiyokosabrey:20200913005345p:plain

 

キャプチャして立ち絵にするあたりは、ちょっとしたテクニックがあるので、また改めて記事にしようと思います。

 

 

 

カリキュラムのカウントアップについて

散らばった一番小さいBallには、0~223 の固有のID番号を振るようにしています。

最初マップに配置する一番大きいBallには 0~6の番号を与えておきます。

f:id:hiyokosabrey:20200913110009p:plain

それぞれがActorでプレイヤーと接触すると2番目の大きさのBallを自身の周りにスポーンさせて自身はDestroyします。

この2番目の大きさのBallをスポーンさせるとき、自身の番号に 32を掛けてさらに +0、+8、+16、+24 を加算して持たせます。

f:id:hiyokosabrey:20200913111511p:plain

さらにここから一番小さいBallが 8個 スポーンします。ここはシンプルに自身の番号に0~7の数字を加算しています。ForLoopノードのIndex値を加算するだけです。

 

f:id:hiyokosabrey:20200913112404p:plain

これで最終的にゲットするBall に固有のID番号振る仕組みができました。

今度はあちこちに散らばってしまったBallから、どのカリキュラムのBallかを逆算していきます。ゲットした番号を 32 で割ります。Integer型の割り算なので少数以下は切り捨てられます。

その値を配列を使ってカウントして、画面の棒グラフに反映しています。

カリキュラムが一つMAXになると、集中力の低下がしばらくストップするようにしました。宿題が一つ片付いたので勢いがつくイメージ。

 

 

 

 タイトルロゴについて

まぁゲームが地味なので、タイトルロゴくらいは賑やかにしようと思って頑張ってみました。テーマ回収をここでしてる感がありますが・・・ぶっちゃけあります。

f:id:hiyokosabrey:20200913004339p:plain

 

無理やりラノベ感を出そうとしてちょっと痛々しさも感じつつもう少し手を入れたいと思う自分がいたり。というわけでちょこっとコントラスト上げてみた。

 

f:id:hiyokosabrey:20200913115544p:plain

 

濃ゆくはなったけど、まだまだ追いついてない感じです。

 

 

 

諦めたこと

ブラックホール的な誘惑ゾーンを作りたかった。エンジンで床に凹みを作ろうとスタティックメッシュのブーリアンを試してみたのですが、UVのスケールを調整しきれなかったのと、エッジを滑らかにできなかったので、DCCツール使わないと無理そうと分かったので断念。

とにかくエフェクト。分解するときにパーティクルを飛ばしたかったけど、普段からエフェクトツール触ってないのもあって、手が止まってしまった。なんとか回復アイテムを取った時だけ出すことができた。前回もエフェクトを思い通りにできなかったのに解決できていないのがまったく反省していない。

 

 

 

 

 

最後に

結果発表の中で、「締め切り駆動」という言葉が何度か出てきて、今回まさにそれだと思いました。実際の仕事ではそんな状況を作ると叱られてしまうのですが、今回は短い時間でのチャレンジがとても楽しかったです。ぱっと思いついてさっと作ってみる。そんな炭酸の泡のようなアイデアでも、無謀にも一人で試してみようと思えるアンリアルエンジンのハードルの低さは素晴らしいです。そこそこ長く触ってきていますが、エンジンを触ること自体のハードルは決して高くないと思います。エンジンの開発およびサポートされている皆様には感謝しかありません。正直使いこなすのにそれほど時間がかからないと思うUE4ですが、厳しい現実と向き合わされることになります。

それは、自分自身が持つゲーム作りの感性。例えば、素晴らしいキッチンと調理道具がそろっている状況で、おかずのレパートリーが少ないのはなぜか?というのを考えると分かりやすいかもしれません。油を熱したことがなければ揚げ物やアヒージョなんて作ろうと思わないと思う。でも食べて感動したら試したくなるじゃないですか。しかも同じ環境、同じ道具で作らてしまうなんて、と。

と言いつつ自分はなかなか試せていない現実が重かったです。

そう考えると ぷちコンはとてもいい環境です。ぜひこのまま続いていってほしいですが、作品数が増えると審査にかかる時間と労力は相当なものになると思います。お忙しい中本当にありがとうございます。

 

次回はエモいの作りたいな・・・

 

 

ではでは

ステキな ぷちコン ライフを!