As Sloth As Possible

可能な限りナマケモノでありたい

アリシアちゃんを動かしてみた話が途中で止まってるけど、先週末第3回Oculus Game Jam@n_mattunと一緒に参加してきたのでその話を。

どんなゲーム作ったの?

こんなの。

どういうゲームかというと、「どうやら軍人らしい人になって何らかの力で手から焔を出して、不死身のマスクマンの軍団を燃やし尽くす体験をする」というものです。企画会議では「この人は何らかの国家資格を持っている上にきっと大佐くらいの高い地位にある」「なんか多分手袋に仕掛けがある」みたいなことが囁かれていたとかいないとか、どっかで見たことがあるような気がするのはきっと気のせいだと思いますよ。君もそう思うだろう?鋼の。

操作方法は、右手にあるものを持って「親指で弾くと指先から火球が飛んでって着弾地点で大爆発を起こす」「人差し指を引くと前進」「中指を引くと後退」「Oculusなのでキョロキョロすると画面内でも視界が変わる」みたいな感じです。右手だけで操作出来るので簡単。

右手に持ってるものは何?

こんなの。

これは何かというと、@n_mattunと一緒に秋葉原であれこれ物色していたときに見付けた、「机に置いてるときは普通のマウス、持ち上げた状態だとトラックボールとして機能する2wayマウス」。

Oculusのゲームを作るにあたってみんな試行錯誤してるのがインターフェースで、Oculus Riftとキーボードやマウスはなにしろ非常に相性が悪い。視界が全部覆われているからどこに何があるか分からないのももちろんのこと、「今自分の見ている世界の中に無いものを使って世界を動かす」ってのをやってしまうと若干夢から覚めるように没入感が損なわれるんだよね、ってのを常々思ってて、それが故にLeap MotionやKinectなんかのモーションコントローラを使ったり、バランスWiiボードに乗ってみたり、Oculusの傾きだけで操作したり、なんてことをやってる人が多い。

んでこれを見付けた時に、「これだったら握ったまま手を自由に動かせるよね」「手触りだけでボタンの位置とか把握できるし見えてなくても操作し易いよね」と言うことで即買い。冒頭のゲームの内容もこいつを活かすにはどういうゲームが良いだろうという風に考えての逆算で出てきたアイディア。こいつを握って手を前に突き出した状態と画面の中での手の位置がリンクして、親指でトラックボールを弾くという動作と画面内の指先から火の球が出るというエフェクトともリンクする、そしたら自分が見てる世界と自分がやってることの違和感が少なくなるかな、というこだわりポイントだったのです。プレゼンでちゃんと説明できなかったけど!

実際に遊んでみてもらった感触は上々で、みんな1回説明すればすぐ覚えてくれたみたいだし、「これはなかなか自然ですね!」って言ってもらえたので、もうちょいブラッシュアップして他のゲームでも使ってみたいと思ってる。

出来なかったこと

本当はこれにさらにLeap Motionを組み合わせて、実際の手の位置と画面内の手の位置を連動させて、ちゃんと手の向いてる方に火球が出るようにしたかったのだけど、残念ながら間に合わずオミット。大体みんな色んな方向に手を向けてみては「あ、腕の向きは固定なんですね…」ってなってた。これがあっちこっち向けられたら楽しいだろうなーと思ってたのでここが一番残念だった。

あと、ちゃんとゲームの体をなす、という意味で、なんらかのクリア目標を設定するとか、マスクマンに襲われたらダメージを受けるとかも作り込みたかったのだけど、これもそこまで到達出来なかった。今現時点では単に「無尽蔵に湧いてくるものの鬱陶しいだけで無害なマスクマンを大火力でひたすら蹴散らす」という謎のデモになっている。折角なのでどっかの体験会とかには出してみたいので、その時までには最低限ゲームとして成立するものにはしたいところ。

他、細かいところだと、本当は「魔法陣は手の甲にデカール、親指シュッと連動して画面上の指先もアニメーション、"稲光のような、見えない導火線のような"エフェクトが走って、任意の”空間”で発火、爆発後も燃え残りのパーティクルが散らばる」みたいな演出にしたかったんだけど、これも実装上の都合で普通に火球を飛ばして当たり判定取って爆発させるにとどまった。

ゲームジャム初体験の感想

周りみんなすごい人だらけだしなんとかゲームらしきものも作れたし、何もかもが超楽しかった、という感想が全てなんだけど、強いて付け加えるならアラサーのおっさんかつド素人が事前準備もせずいきなり30時間耐久ゲーム開発とかするとどうなるかというとこんな感じになるというのを当日の発言から察していただきたい。

UE4とOculus Rift DK2を使ってニコニ立体ちゃんと戯れるデモを作ってみた話の続き、今度はAIを作ってみる前編。

プレイヤーについてくる

まずはアリシアちゃんがプレイヤーについてくるようにする。なんでついてくるのかは分からん。アリシアちゃんはプレイヤーが大好きなので片時も離れたくないのかもしれないし、不倶戴天の敵なので見付け次第抹殺しようとしてるのかもしれない。その辺は適当に脳内で補ってください。

とりあえずおいかけっこ

ただ単にプレイヤーを追尾するだけならめちゃくちゃ簡単。

まずはマップにNav Mesh Bounds Volumeを配置する。ビューポート上でP押すか、「表示」から「Navigation」のチェックを入れてやるとAIが歩ける範囲が確認できるので、地面が黄緑色になってるのを確認する。

黄緑色

次はアリシアちゃんのCharacterとAIControllerを作る。キャラクターが親のBP作ってコンポーネントにアリシアちゃんのメッシュを設定し、AIControllerが親のBP作ってCharacterのBPのAIController Classにそれを指定してやる。

AIControllerのEvent GraphにAIの処理を書いてやるんだけど、TickイベントでGet Player ControllerしてSimple Move ToでGoalに設定してあげればいい。こんな感じ。

簡易プレイヤー追跡ロジック

これであとはスケルタルメッシュではなくキャラクターの方をマップ上に配置してプレイしてみると、アリシアちゃんがついてくるようになる。ルートの探索とかはAIControllerが勝手にやってくれるので便利。これだけでも案外楽しい。デフォのMax Walk Speedだと早すぎて一瞬で距離を詰めてくるので、200くらいに設定してみた。

一定の範囲に入ったときだけプレイヤーを発見する

取り敢えず追いかけっこは出来るようになったものの、常についてくるのではなくて条件次第で別の動作もさせてみたい。そのままBPでゴリゴリ書いていってもいいんだけど、どうやらAIの制御をするのにはそれ用にビヘイビアツリーというのがあるようなのでそれも使ってみることにする。

何の事はない、ビヘイビアツリーのクイックスタートガイドにまんまプレイヤーの追跡をするビヘイビアツリーの作り方が書いてあるのでそれをそのまま実装してみる。何か色々やってるように見えるけど読んでみると結構簡単。

まずMultiSphere Trace for Objectで一定範囲内に何らかのActorがあるかチェック。ObjectTypesにはPawnを指定しておくと、WorldStaticに設定されてる床とか壁とかは拾わずプレイヤーとかだけ拾う。

その後、AIがコントロールしてるActor(この場合はアリシアちゃん)の位置からさっき見つけたActorまでLine Traceする(ドキュメントだとSingle Line Traceって書いてあったけど4.5だとノード名がLine Traceになってる模様)。これはUnityだとRaycastってのに相当するみたい。

こちらはfor Objectではなくby Channelになってる。さっきは指定したObject Typeのものを引っ掛けていたのでPawnを指定していればPawnだけ拾ってたけど、今度はコリジョン応答>トレース応答>Cameraのブロックにチェックされてる奴はなんでも拾う。MultiじゃなくてSingleの方を使ってるのが肝で、最初に見つけたのがSphere Traceの時に見つけたのと違う、この場合はプレイヤーとアリシアちゃんの間に遮蔽物がある場合は「見つからなかった」ことにしてる。無事見つけたらブラックボードにプレイヤーActorをTargetToFollowに登録。見つからなかったら削除。

TargetToFollowが設定されてたらツリー上の左側の方の処理が実行される。RapidMoveToタスクは大分大雑把に言うとさっきのAIControllerに直接書いたやつと大体一緒で、AIControllerが制御してるActorをTargetToFollowのActorまで移動させている。

1個戻ってCloseEnoughデコレーターを見てみると、ターゲットと自分との距離を測って指定した距離より近くにいるならfalseでCondition Checkを終えるので、その先の移動処理は実行されない。十分に近付いてるならAI Move Toしないので無駄にAIにルート探索させないし、さっきのだと常にアリシアちゃんがこっち向いてくるので出来なかった「後ろに回りこむ」が出来るようになるし、Acceptable Distanceを長めに取ると一歩下がって遠くから眺めるとかも出来るようになる。

プレイヤーを追いかけていないときは…?

ツリーの左側の処理がプレイヤーを見つけて追いかけている時に実行されるので、プレイヤーを追跡中じゃない時の処理を作りたければ右側の方に書けばよさそうだ。こっちはサンプルとは違う動きを作って行くことにしたのだけど、長くなってきたので一旦切って後編に続きます。

UE4とOculus Rift DK2を使ってニコニ立体ちゃんと戯れるデモを作ってみた話の続き、今度はモーションを付けてみる編。

アニメーションリターゲットを使う

前回インポートするときに一緒にアニメーションを取り込めなくてどうしたものかと困っていたら、UE4.5から、異なるスケルトン間でアニメーションを使い回せるアニメーションリターゲットの機能が入っていたらしい。つまりあの人の動きをアリシアちゃんにも付けられるわけだ!素敵機能だ!

blueman2

泣く子も黙る我らがブルーマンさん…のアニメーションは「ライフルを構えて走る」とか「撃たれて死ぬ」とかなので、アリシアちゃんに適用するにはちょっと…。ということでマーケットプレイスから入手出来るMixamo Animation Packから待機モーションと歩きモーションを貰うことにする。

基本、ドキュメントに書いてある通りにやればいいんだけど、まずハマったのがアニメーションをリターゲットしようとした瞬間の突然のUEのクラッシュ。何回やってもクラッシュするんだけど、クラッシュログがAssertion Errorとかで情報量無くて何が原因だか分からない。

色々試してたらlowerbodyとupperbodyの両方のボーンがノードに割り当てられてるときにクラッシュする様子(片方ずつならクラッシュしなかった)なので、upperbody外してみる。これでアリシアちゃんも歩けるように…

motion

…ならなーい。はい。こうなることはある程度予想してたので慌てちゃだめです。スケルトンツリーからupperbody01を選んで平行移動のリターゲティングを「スケルトン」にしてやると無事上半身と下半身が繋がった。

これで調子にのって走りモーションもリターゲットしてみたんだけど、こっちはいまひとつ。というのも、アリシアちゃんのheadのボーンとリターゲット元のそれの高さが違うので、元は前傾姿勢で走ってるモーションなんだけどアリシアちゃんにあてると頭が微動だにしないまま体は全力疾走みたいになってしまう。あと、そもそも割と走り方がいかつい感じなので、上手く調整してもあんまり似合ってない感じだった。

マーケットプレイスにいかにも日本人が喜びそうな可愛らしい走り方やダンスのモーションを含んだアニメーションパックが出てくれないかな、と願うところである。

アリシアちゃんが動き出すようになって楽しくなってきたので、その3、追いかけっこをしてみる編に続きます。

先月Oculus Rift DK2が届いたので折角だしゲーム制作に挑戦してみよう、ということでニコニ立体ちゃんことアリシア・ソリッドの3DモデルをUE4で取り込んでOculusで戯れてみることにした。

Oculusを使って、と書いたけど別にOculusが無くても戯れられます。というか、Oculus表示が出来るというだけでOculusならではなことは特にしてません。

マップを用意する

いきなり自分で1からマップ作ってくとなると結構ハードルが高いので、今回はマーケットプレイスから入手できるブループリントオフィスのマップをそのまま使わせてもらう。

Epic Gamesが提供しているサンプルプロジェクトはちょっと尋常じゃないクオリティなんだけど、サンプルプロジェクトで使われているアセットは自作のゲームにも流用可能なので、取り敢えず何か作ってみようみたいなときにそこから始めるといきなりなんかかっこいい感じになってテンションが上がります。まだ何もしてないのになんかすごいの出来ちゃった感が出る。まだ何もしていない。

それはそれとして、見てるだけでもかなり勉強になるので積極的にサンプルプロジェクトを弄ってみると良さそう。あれどうやるんだろう、みたいのがContent Examplesに大体あったりする。

モデルを読み込む

Alicia_solid_Unity.FBXをインポートする。取り敢えず何も考えないでインポートしてみたけど、よくある「モデルが寝てる!」とかもなく普通に読み込めた。ちなみに開発時点では配布開始直後だったのでVer.1のを使ってるけど、記事書いてる時点ではVer.3まで出てました。

が、哀しいことにモーションはちょっと大変なことになってます。頭の中で「ゲッダンんーふふんーふふんーふふんーふふーふふふー」みたいなBGMが流れました。

インポートのオプション良くわかってなくて間違えたかなーとか思ったけど、他の3Dモデリングツールで開いてもアニメーション上手く見れないみたいな話を聞いたので、結局諦めてアニメーションのインポートのチェックは外してメッシュだけ読み込んだ。

見た目の調整

勇んでインポートしたままのスケルタルメッシュをポンと配置すると、(特にアニメ調のキャラクターのモデルだと)あ、あれ??なんか思ってたのと違う…みたいな気持ちになる。

default

…まずは見た目を調整しよう。こっから試行錯誤。

とりあえずUnlitにしてみる

こんな感じ

unlit

スケルタルメッシュをダブルクリックして表示してみて、ライティングなしの表示に変えてみると、元々のテクスチャそのままの表示になるのでそれっぽく見える(当たり前)。ようしそれならとすべてのマテリアルのShading ModelをUnlit(ライティングなし)に変えてみる。置いてみます。超、浮いてます。

真っ暗闇のマップにアリシアちゃんだけを配置して眺める分にはいいんだけど、なまじマップがサンプルプロジェクトのおかげでやたらリアルなので、一人だけ全くライティングの影響を受けてないアリシアちゃんがものすごい異物感出る。

真面目にマテリアルを弄ってみる

ちゃんと質感を考慮してないままリアルなライティングが効くところに置いてるからフィギュアっぽい感じになってしまってるので、それぞれマテリアルを調整する。

マテリアルのドキュメントを読むと、どうやらラフネスとかスペキュラとかを調整してやると良さそうだ。

あとそれから、例えば肌や髪、目なんかは石とか壁とかとは光の反射の仕方が違うので、そういう設定をする。Shading Modelのドキュメント読むと肌とかにはちゃんとそれ用の設定があるらしい。このあたりでアリシアちゃんが血色良くなって生き物っぽくなってきました。

それから服、これも布っぽい感じが欲しいところ。なんかそういうのの例ありそうだなと思ってContent Examplesを見に行くとそのままずばりCloth.umapがある。開いてみると、すごい布だ!布感ある!ってなります。でもこれは上手く取り入れられたかというと微妙なところ。もうちょい試行錯誤が必要そう。

調整済み

んで最終的にこんな感じ。

セルシェーディング

リアルさを追求していく方向性ではなくて、アニメっぽいキャラなんだからアニメっぽくレンダリングしてあげれば良いのでは、の方向性。というより、あれ?って思ってニコニ立体の配布ページに見に行くとそう(セル画風のレンダリングに)なってるし、モデラーさんの製作過程見ても「トゥーンシェーダー作って適用」みたいに書いてあるので、ならばUE上でもそうしてあげればよいのではということに気付く。

UE4だとポストプロセスでやるやり方があるようで、シモダジュンヤさんのそれを参考にやってみる。

Cell Shading in Postprocess セルシェーディングのポストプロセス

これも一発では上手く行かなくて、影になってるとこに入ると真っ黒になる、みたいなのが起きたりしてかなり試行錯誤した。したけど何したか思い出せないんだ…。いきなり手を出すにはちょっと難易度高いやつだった。

結果多少はそれっぽい感じにはなったんだけど元の見た目に忠実ってとこまではなってないし、一方マテリアル調整してそれっぽくなった版のアリシアちゃんもこれはこれで悪くないよなぁ、と悩んだ末Alicialusでは動的に切り替えられるようにした。セルシェーディングするかしないかはRender Custom Bufferのチェックで決めてるので、Cキー押すとBPでメッシュのRender Custom Bufferをトグルするようにしてある。口で説明するより見た方が早いのでデモで試してみてください。

ライティング

モデル自体のマテリアルやレンダリングの仕方もそうなんだけど、そもそもの話としてライディングがどぎついというのもある。実は、弱めのポイントライトが配置された室内とか、反射光で照らされる木陰とかだと、取り込んだそのままでも思ったよりそれっぽく見えるし、マテリアル調整後やセルシェーディング有効にしてても直射光が当たってるとこだと眩しくて微妙な感じになる。

んじゃライティング調整すればって話なんだけど、今回マップが自分で1からセットアップしたやつじゃなくてサンプルプロジェクトのやつを使わせてもらってるので、ディレクショナルライトの光自体を弱めちゃうと全体が暗くなって雰囲気が変わってしまうのでやらなかった。同じくポストプロセスで色々と弄っても調整可能なのも分かってるけど、それも全体に影響するのでちょっと悩み中。

長くなってきたので一旦切ろう、その2、モーションを付けてみた編に続きます。

Rustで遊んでみよう第二弾、本当は並列処理を試してみたにする予定だったんだけど何故かHTTPパーサが出来てた。

経緯はこう。

「並列実行できるクローラ作ってください」「作るってどのレベルで?HTTPパーサから?」みたいなのがRust村みたいです。まぁ言うてまだアプリケーション層だ。TCP/IPからなんとかしましょうとか言われなくてよかった。一応C国からの輸入は許されてるけど、TLSとかならともかくHTTPくらいなら自力でなんとかできるでしょ、普段そんなの車輪の再発明だしやんないからいい機会だ、ってことでご用意しましたのがこちらになります

一応それらしいものにはなって、ステータスラインやリクエストラインの処理、ヘッダをフィールド名と値に分解、keep-aliveやupgradeの検出、chunkedなボディのデコード、くらいはできる。

ソース見ると一瞬うってなるけど、やってることはといえば、愚直に与えられたバイト列を1バイトずつチェックしてって適宜コールバックを呼ぶ、これだけ。TcpStreamには直接は触らないし、正規表現や文字列のパターンマッチはおろかcharへのキャストすらしてない。パースした結果を構造体に詰め直すとかはコールバック側で勝手にやってくださいのぶん投げ。

もっと綺麗に書けるのになんでこんなことになってるかというと、素直に書いてもつまらないので、crazyな速度と評判のCで書かれたhttp-parserを参考に速度最優先で作ったから。その甲斐あって400バイト強の普通のブラウザのGETリクエストをただパースするだけなら、手元の環境だと3~5μsくらいで 処理できるようになった(--opt-level=3でコンパイルしたとき)。

(試しに10万回ぶんまわすサンプルコード書いてみて、元のCのやつと比較してみたら、Cの方が550ms程度なのに対して俺が書いた方が330msで終わった。…なんで勝ってんだろ。多分なんかの間違いだろうなー。実装漏れしてるとか最適化でほぼ何もしなくなるコードになってるとかそんなとこだとは思う…。)

そんな感じで何もない荒野を耕しては雑草植えてますけどこれ結構楽しいです。んでよーやくHTTPクライアントに手を付け始めたけど、こっちの方は今任意のリクエスト投げて結果を表示するとこまではできた。keep-alive、リダイレクトも対応、Content-Typeにcharsetが付いてたらその文字コードでボディをデコードもできる。あとやりたいのは、POSTでフォームデータとかファイルとか送れるようにするのと、gzip/deflate対応と、TLSサポート(LibreSSLとSecure Transport選べるようにとかしたい)あたりか。まだ先長そうだなー。

↑このページのトップヘ