るっちょ らいつ

るっちょ ぷれぜんつ 開発の日々。

Unity 1週間ゲームジャム「密」開発記録

f:id:ruccho:20200504004136p:plain

unityroom で2020年5月に開催されたUnity 1週間ゲームジャム「密」に参加しました。

 

 

 

 「コロニーズ」は、細菌を操作して、仲間の細菌との密集や分裂を繰り返しながら数を増やしていくシューティングゲームです。

 

 

開発記録

月曜から日曜までの開発記録を連ねてきます。

月曜日

 

 とりあえずテーマを「分離と密集を繰り返すシューティング」とし、プレイヤーの移動や弾の発射などの基本的なアクションを整えていきました。

 あと、今回はレンダリングパイプラインにUniversal Render Pipelineを使用しました。URPにはスプライトに対しライティングを適用することができるLights 2Dが搭載されており、Lights 2Dを使った絵作りをやってみたかったのです。

 

火曜日

 撃った弾で仲間を増やしたり、仲間とくっついたりできるようになりました。

 

  そしてこの日、問題が発生します。試しにWebGLビルドして動かしてみたところ、Lights 2Dの影が一切出なくなるという事態に。「Lights 2D、実はWebGL未対応だったりして……」などという不穏な考えが頭をよぎったりしてめちゃくちゃ焦りましたが、いろいろと条件を変えて検証したところ、「プロジェクト作成時にURPテンプレートで開始するとビルド後にLights 2Dが無効になる」ということがわかりました(自分でもよくこんな条件を見つけたなと思います……)。

 原因がわかったので、あとはURPテンプレートでないプロジェクトと今回のプロジェクトで設定などを比較し、WebGLビルドでLights 2Dを動作させることができるようになりました。本当によかった!!

 前回の参加(Unity1週間ゲームジャム「あつめる」に参加したよ - るっちょ らいつ)のときもビルド後に初めていろいろな問題が発覚したりしたので、そういった経験を踏まえて早い段階でWebGLビルドを行ったのですが、功を奏したようです。早期のWebGLビルド、大事!

 

水曜日

 さて、このゲームの操作プレイヤーは一人ですが、自分以外の細菌たちはすべて勝手に敵を撃ち、集合や分裂を行います。このAIをうまく作れるかが今回の鍵でした。

 AIの思考は、基本的には一定間隔で画面内の細菌を取得し、それらに対して距離・体力・サイズ・仲間の数などを考慮して重みづけを行い、優先度の高い敵をターゲットとして設定し、あとは撃つというものです。ゲームAI開発に関する予備知識が全然ないので、度々「こんな作り方でいいのか……?」と思いながらの開発でしたが、そこそこいい感じに動いてくれるようになったと思います。

 AIの基本的な動作ができたので、ふと思い立ってAI同士で戦わせてみました。するとこれが結構面白く、ずっと眺めていられるのです!そこでゲームに「観察モード」を入れ、タイトル画面の背景ではAI同士のバトルを展開し、またプレイヤーが敗北した後もバトルの続きを眺めていられるような仕組みをつくりました。また、「このゲームは細菌を観察しているという体」をコンセプトとし、オープニングやアートスタイルに反映させていきました。この「観察」というアイデアは自分でも結構気に入っています。

 

木曜日

 この日はAIの調整とオープニングの作成、そして分離アクションの実装を行いました。

 

 

金曜日

 このあたりからゲームの細部を整えていく作業になってきます。具体的にはUI作成、アニメーション、チュートリアル作成、バグ潰し、最適化などです。特に最適化については、この段階までほとんどパフォーマンスの検証を行っていませんでした。普段使っているマシンはそこそこハイスペックなのですが、ビルド後はWebGLになるのでいろいろと制約があるうえ、普通のノートPCとかでも動いてくれないと困ります。手持ちのノートPC(i5でグラボなしのインテルGPU)でWebGL動作検証を行ったところ、15FPSという少々ショッキングな数字が出てしまいました。特にLights 2Dの影の描画が各細菌に対して行われるため、このゲームではかなりのネックとなっていました。これに関しては画面外の影描画の省略が一番効いた感じがします(Lights 2Dで大量のスプライトを描画する際はぜひ参考に)。それでもそこそこ負荷が高いので、最終的にはFPSを測定して自動的に影の描画の有効化・無効化が行われるようになっています。

土曜日

 引き続き、細部の調整作業を無限に行っていました。そしてここにきて初めてサウンドに着手します。とりあえずbfxrで一通りSEをつくりました。ゲーム中、常に響き渡る弾の発射音は5種類のAudioClipをランダムに切り替え再生してできるだけ単調にならないようにしています。

 

日曜日

 ゲーム本体に関してはBGM、バグ潰し、サウンド関連の最適化作業だけ行い、早々にビルド・アップロードしてしまいました(期限ギリギリになってWebGLビルドが終わらない絶望感を知っているので)。あとはツイート用動画の収録・編集、アイコン作成など公開関連のこまごまとした作業……これまでになく万全の状態で20時を迎えることができたと思います。

 

総括

 ゲーム内の細菌の総数は105に設定されています。そのうちプレイヤーが同時に操作できる細菌はたったのひとつです。つまり、勝敗はプレイヤーの技量によってあまり左右されません。まあ例えば彷徨い歩く細菌を回収して激戦区に展開する、みたいな戦略はアリですが、フィールドは広いですし、結局のところは運ゲーの部分が大きいです。当初このコンセプトで開発を開始するとき、これで本当に面白くなるのかどうかあまり自信がなく、余力があればオンライン化して対人対戦ゲームにしようと考えていました。最終的には(余力がなかったからでもあるのですが)オンライン機能なしで公開することとなりました。

 実際には仲間のAIプレイヤーが敵に奪われると申し訳ない気持ちになるし、全滅直前に孤軍奮闘してるときも凄く孤独感があります。あと、コメント欄には「敵にボコボコにされたけどそれも面白かった」という声が寄せられました。このゲームの面白さの要はシューティングゲームとしての面白さではなく、どちらかというとAIプレイヤーに対する愛着感や「観察してる感」にあるんじゃないかな?と思っています。そういう意味で「観察」を一つのコンセプトに設定したのもよかったのかもしれません。

 まあ、105のセルを全部プレイヤーにしてオンライン化するのはさすがに無理があるにしても、各カラーひとりはプレイヤーにして対人ゲームにするのはまあアリだと思います。ただunity1week参加時は毎度のことながらコードがぐっちゃぐちゃになるのでオンライン化は茨の道になりそうです……(ただでさえバグが頻発してるのでそちらもどうにかしないといけない)

Unityのリアルタイムレイトレーシングを試す

f:id:ruccho:20200121231449p:plain


Unityのリアルタイムレイトレーシング機能(DXR)は、2019.3以降、HDRPで使用できます。DXR対応のグラフィックスカードが必要です。

対応カードは以下の通り(公式ドキュメントより):

  • NVIDIA Volta (Titan X)
  • NVIDIA Turing (2060, 2070, 2080, and their TI variants)
  • NVIDIA Pascal (1060, 1070, 1080 and their TI variants)

 

記事執筆時点で2019.3の最新版はUnity 2019.3.0f5でまだベータなうえ、レイトレーシング機能もまだpreviewなので手順が変化している可能性が大いにあります。要するにいち早く試したい人向けの記事です。

 

内容は概ね公式のドキュメントにのっとっています。都度参照していただけるとより分かりやすくなると思います。

docs.unity3d.com

 

また、すでに設定されたプロジェクトファイルも公式から配布されているので、動くところを見たい人はそちらをダウンロードするとよいでしょう。本記事では新規プロジェクトのセットアップ方法を書いていきます。

 

 

やっていき

まずはUnity 2019.3以降でHDRPテンプレートの新規プロジェクトを作成します。

 本記事では2019.3.0f5を使用していきます。

その①: DXR用の諸設定をおこなう

驚くべきことに、HDRPの各種設定をウィザード形式で行えるようになっています。(HDRPの設定むずかしいから大変ありがたい)

Window > Render Pipeline > HD Render Pipeline Wizard

でウィザードを開きます。

 

f:id:ruccho:20200121003052p:plain

 

すると、「HDRP+DXR」といういかにもなタブが現れますので、選択し、「Fix All」ボタンで自動的に設定を行ってくれます。(ウィザードですらないような簡便さである)

 

f:id:ruccho:20200121003329p:plain

 

途中、Graphics APIDirectX 12に変更されるので、エディターの再起動を求められます。再起動後、Fixが途中で止まっていることがあったので、もう一度Wizardを開いて確認しておいた方がいいかもしれません。

 

その②: シーンをセットアップ

いろいろ設定を自動でやってくれそうな雰囲気でしたが、レイトレーシングはまだ有効になっていません。実際のシーンに対して個別の設定が必要になってきます。

 

まずはシーンを作ります。レイトレーシングのうまみが出そうな感じのシーンを作ってみましょう。

f:id:ruccho:20200121224230p:plain

とりあえずコーネルボックス

 

ちなみに、部屋のライトと、Volumeの設定は次のようになっています。VolumeのデフォルトのプロファイルはPackagesの中にあるのでちゃんとNewしないと設定が差し戻ったりするので注意です(うっかり設定を全部飛ばした顔)。

 

f:id:ruccho:20200121224525p:plain

 

その③: レイトレーシング設定

レイトレーシングの各種機能を試してみます。

Ray-Traced shadows

f:id:ruccho:20200121225614p:plain

Lightが落とす影をレイトレーシングでつくります。デフォルトの影より影の輪郭が自然な感じになります。

設定はLightコンポーネントのShadowセクション内のRay Traced Shadowを有効にして行います。

f:id:ruccho:20200121225302p:plain

Denoiseを有効にしないとノイズが出て汚いです。これ以降、各種レイトレーシング機能ではデノイズのオプションがあることが多いので、うまく使っていきましょう(デノイズに関してはこれ以降割愛します)

 

Ray-Traced Global Illumination

f:id:ruccho:20200121230442p:plain

事前計算無し、(ほぼ)完全リアルタイムでGIを利かせられます。

 

Ray-Traced Global IlluminationはVolumeから設定します。Add Override > Ray Tracing > Global Illuminationで追加します。

f:id:ruccho:20200121230225p:plain

 

Ray-Traced Ambient Occlusion

f:id:ruccho:20200121231449p:plain

レイトレーシングを有効にした状態

 

f:id:ruccho:20200121231837p:plain

レイトレーシングを無効にした状態。もうちょっと複雑な形状の方が違いが分かりやすいかも

 

こちらも同じくVolumeから追加できます。Add Override > Ray Tracing > Ambient Occlusion にあります。

f:id:ruccho:20200121231334p:plain

 

 

Ray-Traced Contact Shadows

Contact Shadowsは、物体の接地部で影が切れる現象を補正する処理です。

f:id:ruccho:20200121233606p:plain

左: 無効時 右: 有効時

こちらの設定は、VolumeでContact Shadowsを追加したのち、Lightコンポーネントの設定でContact Shadowsを有効にする必要があります。

 

f:id:ruccho:20200121234026p:plain

Volumeの設定。



f:id:ruccho:20200121234141p:plain

Lightの設定。

 

Ray-Traced Screen Space Reflection

f:id:ruccho:20200121234434p:plain

Screen Space Reflectionを有効にして、マテリアルをいじった状態。

マテリアルの反射表現をレイトレーシングで行うことができます。標準のScreen Space Reflectionでは像が破綻したり、反射されない領域ができたりしていましたが、こちらは整合性のとれた絵が出せるようです。

 

こちらはVolumeから設定します。 Add Override > Lighting > Screen Space Reflectionで追加できます。

f:id:ruccho:20200121235041p:plain

 

ひとつ注意点として、この設定内のMinimum SmoothnessよりSmoothnessの値が小さいマテリアルに対しては効果が出ません。Volumeかマテリアル、どちらかの値を調整します。(Smoothnessが小さいマテリアルに対しては高負荷になるのでしょうか?)

 

Path Tracing

f:id:ruccho:20200121235627p:plain

Path Tracingを有効にすると、リアルタイムではなく、CGツールのレンダリングのように、じっくり絵を作ることができます。

 

f:id:ruccho:20200122000853p:plain

リアルタイムじゃないので屈折処理とかも正しく行える


設定はVolumeから行います。Add Override > Ray Tracing > Path Tracingで追加できます。

f:id:ruccho:20200122001008p:plain

 

追加すると、Gameビューでレンダリングが走り始めます。

 

おしまい

今回紹介した以外にもいくつか機能があるようですが、使い方が微妙にわからなかったのでひとまずここまでとさせていただきたいと思います。画面の品質はこれまでもベイクすれば高めることができていましたが、注目すべきは今回の絵が(Path Tracingをのぞいて)すべてリアルタイムに出せるという点だと思います。ベイク時間も省けますし、もっと一般的に使えるようになったらうれしいですね!

Unity1週間ゲームジャム「あつめる」に参加したよ

「あつめる」

 

こんにちは、るっちょです。unity1weekふりかえりエントリです。

開発記録を適当にまとめます。

 

月曜日

月曜にはプロジェクト作成ボタンを押してました。ただ、マジでアイデアが何もなかったので、脳死でよさげな絵をつくってそこからアイデアを広げるという作戦で、まず最初に出来上がったのがこれ。

 

 

 

目論見通り、ここからアイデアが固まりました。惑星を操作して衛星を集めるという方針でいくことに。

さっそくプレイヤーの素材を描きました。

 

なんにも下書きしないで描いたものですから、このアニメだけで30枚超えてました。正直アホだと思います。

 

 素材を突っ込んで、衛星をつくって、とりあえず基本的なプレイヤーの動作を作りました。

 

水曜日

この時点だとプレイがあまりにも単調なので、何らかのストレス要因を足そうと思っていました。

そこで、前々からやってみようと思っていたオンライン化をして、対戦ゲームにすることにしました。

使ったのはPhoton Unity Networking 2 (PUN2)。無印PUNから刷新された新バージョンですが、まだあまり情報が多くないのが難点です(特に日本語の情報が)。その中でこのチュートリアルの存在に超助けられました。

 

connect.unity.com

(書いているのはUTJの方だそうで……!どうりで内容が充実している……!)

 

基本的な作法から、ちょっと中級者向けの注意事項なども載っていて、これがなかったら今回の開発は頓挫してたかもしれません。

 

……で、とりあえず複数プレイヤーが参加できるようになりました。

 

一通りのロビーの動作なんかも作って、ここらで一回WebGLビルドをしておこうと思い立ってやってみたところ……

 

 

ウン……

 

なんか動きませんでした。

 

木曜日

問題は木曜日に持ち越されました。

とりあえず考えららえるところとして、

・PUN2のバージョンが古い(別プロジェクトで使ってたスクリプトを再利用したため)

・wasmかIL2CPPがなんか悪さしてる

・コードストリッピングが効いている

らへんがあったので、とりあえずPUN2のバージョン上げてコードストリッピング切ってDevelopment Buildにしてみたら、すんなり動きました。

(ここ、実際にどれが原因だったのかはわかりませんが……「なんで動かないのかわからないより、なんで動いてるのかわからない方が怖い」案件ですね)

 

……ひとまずひとやま超えたので、ずんずんいきます。

UIやら、オンライン接続時の動作を整えたりなんかして、良い感じになってきました。

 

土曜日

ゲームバランス調整です。

ただ衛星の数を競うのではマルチプレイの旨味がないので、攻撃手段を作りました。

 

日曜日

サウンドとかやりました。(というかここまで完全無音状態で開発してました、いっつもサウンド最後になっちゃうの、サウンドに対する意識の低さが窺えてよくない)

 

友人に協力してもらいテストプレイ(とTwitterに上げる用のプレイ中動画撮影)しました。

開発期間が極端に短いので致し方ありませんが、ここで初めて実際に対人で遊ぶことになりました。ゲームプレイの根幹にかかわる部分の検証がここまで後手に回ってしまうのは本当に恐ろしいことです。「ひとりではテストプレイできない」、対戦ゲーム開発の難しいところですね……

奇跡的にゲームバランスはまあ許容範囲(自己評価)に収まってたので、このままアップロードです。

 

公開!

 

 ふりかえり(反省)

友人やunityroomのコメントでいただいたフィードバックから、いくつか問題点が浮かんできました。

 

・なかなかマルチプレイしてもらえない

このゲームはオンラインマルチプレイが基本のゲームですが、ひとりで遊ぶこともできるようになっています。

このゲームのオンライン機能は、誰かがゲーム内で「ルーム」を作成し、そこに別の人が参加するという形式をとっているので、unityroomに遊びに来てくれた人の多くは1人部屋を作ります。結果として、ほとんどの人はシングルプレイしか遊びません。

 

前述のとおり、複数人で遊ぶのを前提としてゲームバランスを考えているので、シングルプレイだとゲームの旨味が十分に伝わりません。ひとりで回遊してひたすら天体を巻き込むだけです。競争も攻撃もありません。このゲームの制限時間3分は複数人プレイを前提として設定している数字ですが、ひとりで遊ぶには長すぎるでしょう。

 

おそらくは、ルーム形式ではなくランダムマッチング形式であればよりマルチプレイしてもらいやすかったな、と思います。

 

・ゲームバランスの甘さ

このゲームでは、「天体を捕まえる」「天体に衝突しないようにかわす」「捕まえた天体を敵に撃つ」の三つのアクションが基本になっています。

 

開発の中盤では、ひとつ天体を捕まえると衛星の数が1増え、天体に衝突すると1減り、相手に投げつけるときは1消費する、というバランスでした。とても自然ですね。

しかし、飛来する天体を交わすのは結構難易度が高く、このバランスでは全然衛星の数が増えない、という問題がありましたし、敵への攻撃が命中した際に敵の衛星の数も自分の衛星の数も同数減少するため、攻撃アクションの旨味が薄い(=あまり撃つアクションをしてくれなくなる)のもよくない点でした。

 

結果として、ひとつ天体を捕まえると衛星の数が5増え、天体に衝突すると2減り、相手に投げつけるときは1消費する、という調整になりました。

……捕まえた天体は一つなのに、衛星が5増えるってちょっと意味が分かりませんね……。

遊んでいて気持ちがいいバランスはこのくらいなのですが……リアリティとゲームバランスの両立、これを解決する方法は少なくともこの開発期間中には見つけられませんでした。

 

結論

・対戦ゲームつくるのつらい

・ゲームバランス調整むずい

 

・……でも「1週間クオリティ」なのですべてが許される。unity1weekはいいぞ

 

(というか、毎度見た目のクオリティをそこそこ凝ってしまって、結果ゲーム性が良く分からなくなるっていうパターンで、今回も例によってそれを踏襲してしまったので、次は気を付けたい……)

 

よろしくおねがいします!

unityroom.com

Unityでドット絵っぽいエフェクトをつくろう

f:id:ruccho:20190616225048p:plain

Unityでドット絵っぽいエフェクトを作るの巻です。

 
注意

「ドット絵っぽい」パーティクルの作り方です。完全なドット絵(ピクセルパーフェクト)にするためには追加の操作が要るので注意してください。

 

方針

円形のドット絵のテクスチャシートを用意してParticle Systemでアニメーションさせます。

 

素材を用意するの巻

 

f:id:ruccho:20190616225726p:plain

 こんな感じで、大きさの異なるドットの円を並べます。Particle SystemのSizeは固定にして、テクスチャのアニメーションで大きさを変化させます。

 

 

素材を読み込むの巻

テクスチャをインポートして、新しいマテリアルにぶち込みます。

Particles/Additiveあたりがいいでしょう。発光してるっぽい表現ができてかなり良いです!(特に炎や爆発におすすめ)

f:id:ruccho:20190616230606p:plain

 

パーティクルを設定するの巻

設定したマテリアルを新しいParticle Systemに適用しましょう。RendererセクションのMaterial欄にあります。

f:id:ruccho:20190616230902p:plain

 

次にテクスチャアニメーションの設定です。Texture Sheet Animationを有効にします。

f:id:ruccho:20190616230956p:plain

Tiles欄に、用意したテクスチャのコマ数を指定します。

 

ここがキモです。Frame Over Timeは「時間ごとのコマ番号」の指定ができるので、ここでパーティクルの大きさを制御できます。作ったテクスチャは一番左が大きく、右に行くほど小さくなるような配置だったので、コマ番号0が一番大きいコマ、8が一番小さいコマになります。

なので、画像のカーブは「開始後すぐに大きくなって、次第に小さくなる」という制御をしていることになります。

 

 ピクセルパーフェクトにする場合は、最後にサイズの指定をします。画面サイズに合わせてStart Sizeを設定します。

例えば画面サイズが640x360で、Pixel Per Unitが32の場合、パーティクルのテクスチャの一コマが16x16なら、Start Sizeは0.5になります。

今回こちらで用意した素材は一コマが17x17なので、17/32=0.53125になります。

私の環境ではこれに加えて2D PixelPerfectのPackageを導入してピクセルパーフェクトにしています。

 

 あとはお好みでColorやEmissionの設定などをしておしまいです。

超かっこいいサウンドライブコーディング環境 "ORCA" であそぼう

f:id:ruccho:20190501022015p:plain

メモリダンプを彷彿とさせるサイバーな画面のなかを、たくさんの文字が躍り音楽を奏でる―――ライブコーディング環境「ORCΛ」 (ORCA) は、特有の機能を持ったアルファベットたちを画面に配置することで音楽を作ることができるソフトウェアです。

 

あっ……好き……(絶命)

 

ダウンロード

Windows / Mac / Linux対応です。

hundredrabbits.itch.io

ORCΛは標準でMIDI出力に対応してるので、デスクトップで鳴らすならLoopMIDIとVSTHostで鳴らすのが普通というところなのでしょうが、実は同じ作者がORCΛで使える音源ソフト「Pilot」を公開しており、圧倒的に簡単に音を鳴らせるので今回はそちらを使います。

hundredrabbits.itch.io

やってみる

 ダウンロードできたらOrcaとPilotの両方を起動します。

f:id:ruccho:20190501012619p:plain

 

 ORCA側の画面にコードを入力していきます。

ORCAでは大文字アルファベットそれぞれが特有の機能を持っており、それらを組み合わせることでコードを構築していきます。詳しい機能の一覧はGitHubにあります。

では早速入力してみましょう。

 

f:id:ruccho:20190501013104p:plain

まずは「D」を配置してみます。Dの真下が点滅しているのがわかるでしょうか。Dは「Delay」という命令で、一定間隔でDの下側に信号(bang)を配置します。bangはほかの命令を実行するトリガーとなるもので、例えばbangの右側に音を鳴らす命令を並べると……

f:id:ruccho:20190501013538p:plain

bangの間隔に合わせて音が鳴りました。

セミコロンは、Pilotで音を鳴らすための記号です。セミコロンの右に、チャンネル番号、オクターブ、音名を並べます。この場合は「Pilotのチャンネル0の音色でオクターブ4、C(ド)を鳴らす」という意味になります。(余談:MIDIで音を鳴らす場合はセミコロンではなくコロンになります)

たとえば、Pilotにはチャンネルが0~Fまであるので、この部分を変更することで音色が指定できます。

 

こういう感じで、ORCAの命令はその左右や上下に入力値や出力値を持ちます。

 

また、D (Delay)の左右がハイライトされてますが、ここはDelayの入力値です。例えばDの右を2に変更すると……

f:id:ruccho:20190501014349p:plain

音の鳴る間隔が短くなりました。Dの右側の値を変更すると、bangを生成するフレーム間隔を指定できます。

ORCAでは処理がフレームという単位で実行され、音の再生、画面や処理の更新はこのフレームごとに行われます。このフレームが全体のリズムをつかさどっており、拍のようなものと考えてOKです。画面下部にテンポと現在のフレーム数が表示されています。 

f:id:ruccho:20190501015026p:plain

 

また、Dの入力値を別の命令の出力値で書き換えることも可能です。

f:id:ruccho:20190501015912p:plain

乱数を生成する命令の「R」(Random)はRの左に乱数の最小値、右側に最大値を置くと、Rの真下に生成した乱数を配置します。

このコードではRの出力した乱数がDの入力値(フレーム間隔)となっており、結果、音が不規則に鳴るようになりました。

 

雑まとめ

……とまあ、こんな感じで、命令ごとの入力値や出力値をつないでいくことでコーディングができるという寸法なのです。

ほかの命令を利用して組み合わせることで、もっと複雑な動作をさせることもできます。こちらの動画で主要なものが紹介されています。

www.youtube.com

この動画内のORCAはバージョンが古いようで、一部の命令の入力・出力値の配置場所が異なりますが、基本は同じです。

 

また、Twitterではハッシュタグ #ORCΛ でたくさんの作例が投稿されています。こちらを見ながら、どこがどうやって動いているのかを観察するのも面白いです。

 

サウンドライブコーディング環境「ORCΛ」の紹介でした!

 

余談

公式が「ORCA」と「ORCΛ」と「Orca」と記法揺れしまくっているので(特殊な文字なのでしょうがない)、どう書くべきか悩んだ結果全部混ざりました。ゆるして。

 

 

https://twitter.com/neauoire/status/1114770190552653824

https://twitter.com/neauoire/status/1114770190552653824

AviUtlとffmpegでDVD-Videoの奇怪な仕様に挑む

とある事情で、とある映像作品の編集とDVD出力を任されました。

編集に使用しているのはAviUtl。

 

今回はAviUtlからできるだけ画質と時間をセーブしてDVD出力するためにいろいろ試した記録をつづります。

 

市販のDVDプレイヤーで再生できるようにするという制約があるので、DVD-Video仕様で出力します。このDVD-Videoというのがどんな仕様なのかというとWikipediaを見れば大体わかります。

 

映像フォーマット:MPEG2

画面サイズ:720x480 (NTSC)

アスペクト比:4:3または16:9

 

あまり古い時代の映像事情に詳しくない私はここで引っ掛かります。

「なんで画面サイズは720x480で4:3として策定されているのにアスペクト比が16:9も選べるんだ?」と。単純にレターボックスをつけるだけでいいのなら4:3だけで決めちゃえばいいじゃないか。

実は16:9の場合でも720x480の画面はフルで使い、アスペクト比情報を別に書き込んでおくことで、再生機器側で横に引き延ばしするんだそうです。なんという……

 

しかしここで問題が発生します。

AviUtl側では1920x816のシネスコサイズで編集しているという点です。

つまり、MPEG2のファイルとしては720x480で出力し、DVD書き出しの際は16:9として記録しつつ、シネスコサイズ対応用のレターボックスをあらかじめつけるというあまりにもあまりな手段を取らざるを得ないわけです。

そこで、これだけ柔軟な出力をするために、ffmpegを活用することにしました。

 

AviUtlからのffmpegを通じた出力にはffmpegOutというAviUtlプラグインを利用させてもらいます。mp4出力のx264guiExで有名なrigayaさんの公開されているソフトウェアです。

 

出力設定はこんな感じです。

f:id:ruccho:20180810221009p:plain

 

出力コマンドです。

 

-target ntsc-dvd -vcodec mpeg2video -vf "scale=720x363,pad=720:480:0:58" -r 29.97

 

キモは-vfオプション欄です。-vfはffmpegにおいて映像にフィルタをかけるための引数で、ここでサイズ変換等を行います。様々なフィルタをカンマで区切って入力すると順番に実行されていきます。

①scale

名の通り、単純に入力映像を指定サイズにスケールします。アスペクト比が変わればストレッチも入ります。ここでは入力映像の1920x816から720x363にリサイズしています。前述のDVD-Video仕様で、16:9として記録して、再生機器側で横引き延ばしされた場合にアスペクト比が1920:816になるよう計算した値が363です。小数点以下は適当に丸めましたが。

②crop

レターボックスを追加するために使用しています。"720:480"は最終的な映像サイズ、あとの"0:58"は左右に0px、上下に58pxずつ黒帯を追加するという意味です。

 

あとのオーサリングにはDVDStylerを使用しました。適切な形式にエンコードされていれば無変換でDVDに書き込めるので、多重にエンコードすることを避けることができます。

Unity公式の機械学習ライブラリが公開されたので試す

概要

blogs.unity3d.com

Unity上で機械学習ができるライブラリが公式より発表されたみたいです。

記事を読んでみると、

・多くの自律エージェントが互いに作用する世界でのエージェントのふるまいをシミュレーションできる(漠然としてるけど行動学とかそのへんかしら)

・車の自動運転技術など産業用アプリケーションに関する研究を物理の効いたUnityの世界で実行できる

・自律的な思考を持つAIプレイヤーをゲームに導入できる

みたいなことが書いてあります。以前からUnityはゲーム以外の学術方面での利用も推し進めてるようですが、やっぱり気になるのは開発するゲームに訓練されたAIプレイヤーを導入できることでしょうか。

ゲームでの機械学習というと、DeepMindのDeep Q-Networkなんかが有名ですが、このライブラリでもDQNが利用できるみたいです。

 


Unity Machine Learning - Reinforcement Learning Demo

 

実際に試す

GitHubに必要なファイルがあるので、CloneするなりDownload Zipするなりします。

まだベータ版ですので扱いにはお気を付けください。

Unityは2017.1以上のバージョンが必要です。

 

Unity Editorでml-agent/unity-environmentを開いて、Assets/ML-Agents/Examples/3DBall内のSceneを読み込みましょう。これはあらかじめ用意されたサンプルシーンです。

 

f:id:ruccho:20170922200023j:plain

 

こんな感じのシーンが読み込まれます。

 

HierarchyからBall3DAcademy > Ball3DBrainのInspectorを開き、Type Of BrainをExternalにセットしてください。学習を有効にするために必要な設定です。

 

実際に学習を行うにはビルドする必要があります。

 

どういうことかというと、学習機能自体はこのプロジェクトには含まれておらず、ビルドしたのち外部ライブラリであるTensorFlowによって行われるようです。

 

f:id:ruccho:20170922200844p:plain

 

 ビルドする前にPlayer SettingsからRun in Backgroundにチェックを入れ、Display Resolution Dialogのチェックを外しておきます。

ビルドはダウンロードしたルートフォルダの中のpythonフォルダに保存します。

 

ではビルドも済みましたし実際に学習……と行きたいところですが、そのまえにpythonの学習環境を整える必要があります。

 

Pythonの設定

まずはPythonをインストールします。ドキュメンテーションにはPython2.7でもPython3でもいけるとありますがTensorflowはWindowsではPython3系でしか動かないようなのでこちらをインストールします。(Macでは2.7系でもうごくっぽいですが未検証)

Python Release Python 3.6.2 | Python.org

インストールが済んだらコマンドプロンプトからpython --versionを入れてPython3系がインストールされてることを確認しましょう。

 

では設定に移ります。先ほどビルドを展開したpythonフォルダに移動し、

pip3 install .

を入力すると自動で必要なパッケージ類をインストールしてくれます。

 

学習

インストールが済んだらいよいよ学習を始めていきます。

pythonフォルダーで jupyter notebook を入力してjupyterを立ち上げます。

ブラウザから localhost:8888 にアクセスし、 PPO.ipynb を開いて Hyparameters セクションの env_name にビルドしたバイナリの名前(拡張子抜き)をセットします。

また、デフォルトでは訓練を 5e5(50万)回行う設定になってますが、筆者のPCは貧弱なのでこれを減らしておきます。

Hyparameters セクションの max_steps を5e4に変更します。

 

一番トップのコードのセクションにフォーカス(青カーソルが出る)を合わせ、 Run をカチカチと押してすべてのコードを実行していきますと、ビルドした実行ファイルが立ち上がり、学習が始まっていきます。

 

しばらく放置すると Train the Agents セクションに学習してるログが吐かれます。

 

Mean Reward: 9.350500454959013
Mean Reward: 76.65897435897344
Mean Reward: 88.24444444444323
Mean Reward: 56.52788461538383
Mean Reward: 54.5907834101375
Saved Model

 

こんな感じで続いていき、学習が終了するとビルドしたアプリケーションが終了します。

python/models/ppo/<バイナリ名>.bytes

があることを確認してください。これが学習データです。こいつをExamples\3DBall\TFModelsに移動しておきます。

 

学習した結果を確認する

こんな感じで学習が終了したので、こんどはこれをUnity Editorに読み込んで結果を確認してみます。

もう一度さっきのプロジェクトを開きます。

まず、TensorFlowSharpのunitypackage をプロジェクトに追加します。

Player Settings で Other Settings から、

1) Scripting Runtime Version を Experimental (.NET 4.6 Equivalent) にセット

2) Scripting Defined Symbols に ENABLE_TENSORFLOW を追加

したのち、一度Editorを再起動します。

 

3DBall のSceneを読み込んで、最初に設定したBall3DBrainのInspectorを開きます。

Type Of BrainをInternalにセットし、Graph Modelに先ほど移動したbytesファイルをセットします。

Graph PlaceholdersのSizeを1にセットし、

Name : epsilon

Value Type : Floating Point

Min Value : 0

Max Value : 0

に設定します。

 

ではいよいよPlayしてみましょう。板がボールを落とさぬよう勝手に傾きを調整しています。

 

感想

 とりあえずWikiのまんまに一通り試してみましたが、数多ある機械学習ライブラリとそのサンプルの中では圧倒的に手軽にすごいことが試せますね。(どこでもMNISTしかやらないから)

 

これがUnityという強力なプラットフォームで実現可能になった効果は大きいと思います。カスタムのプロジェクトでのML-Agentsの導入方法についてもWikiにあるのでまだまだいろいろなことが試せそうで夢がひろがりんぐしてます