最近Unity 1週間ゲームジャムに参加しました
完成した作品がこちらです。
ゲームのネタについて
何かを薄く切っていくゲームを考えていたところ
ちょうどこちらのバズっていたとても面白いツイートを見て、題材はパンの薄切りゲームにすることにしました。
第2回食パン薄切り選手権をまたもやひとりで開催してみた。— じゅん@おぐべーぱん魔王 (@J_buriburi) 2018年6月5日
前回の教訓を活かし本気で挑んだらまさかの77枚に切れました。
自己ベストの47枚を大幅に超えてしまって笑ってる。 pic.twitter.com/4JBqk3aML4
使用したアセットについて
Mesh Cut
このゲームで一番大事なメッシュを切り刻むことができるアセットです。
アセットストアにあるものをいくつか見て回ったのですが、どれも$30以上しました。
$30するアセットは、その値段に見合う豊富な機能を持ってることが多く、使い方の学習に多くの時間を取られがちです。
今回はこちらのMIT Licenseのコードを使わせていただくことにしました。
ソースが公開されてるおかげで、改造も可能で助かりました。
Realistic Bread
パンです。$2.69でナイフとまな板がついてきます。
ファンシーハートフォント
とてもかわいいフォントです。これをTextMeshProで使ってます。
効果音
かわせるかしら?などの掛け声も効果音ラボサイトのアセットを使わせていただきました。
音楽
タイトル画面とゲームオーバー時の音楽です。
実装について
パンを切る部分を光らせた
どこがどう切れるのか明示しないと納得感が薄かったので、パンに切られラインを表示しました。
このラインはパンのシェーダーに「シェーダーパラメーターで与えた面との距離を調べて、近いほど光らせる」という処理を入れて実現してます。
もっといい方法はあるはずですが、自分が一番手っ取り早くできそうな方法でやってます。
ゲームジャムですからね。
背景はスカイボックス
パン包丁まな板以外は普通にUnity標準の青空だったのですが、クッキング感を出すために背景をチッキンにすることにしました。
ただ、キッチンのモデルを本当に配置したら、容量、実行速度などに大きな影響がでます。
そこで、テラシュールブログさんの「背景をスカイボックスで表示する」と同じ手法を使いました。
別プロジェクトにキッチンモデルアセットをインポートし、そこでライトを焼き、キューブマップを撮影し、それをパン切りプロジェクトに移行してます。
容量12MBまで削減
WebGLで実行するものは、やはり容量が少なければ少ないほどサーバーにもユーザーにも優しいはずです。
何が容量を占めているのか、勘で闇雲に作業してはコスパが悪いです。
そこで役に立つのがビルド後レポートツールです。
アセットストアにはそれ系のツールはいくつかありますが、自分はこれを使用してます。
アセットストアにはそれ系のツールはいくつかありますが、自分はこれを使用してます。
Better Build Info - Report Tool
何が容量を占めているのか?を一覧で見たり、2次元の面積図で見れたりと、一気にわかりやすくなります。
自分のプロジェクトで大きかったファイルは「日中韓すべての文字が入ったフォント」
自分のプロジェクトで大きかったファイルは「日中韓すべての文字が入ったフォント」
「パンモデルなどのテクスチャ」が多かったです。
フォントは、漢字などが出ないのはもう切り捨てて、「ふぁんしーはーとフォント」で全部表示するようにし、大きいフォントファイルは削除しました。
ランキングで登録する人も、アルファベットかひらがなカタカナ登録が多いようでしたので。
ゲームジャム作品ですし、ランキングで漢字が使えることより、容量が軽いほうがいいでしょう。
テクスチャは、問題がないレベルまで解像度を下げたり、無駄にアルファを使う設定になってるものはアルファを使わないように設定し直すなどしました。
無駄にアルファを使う設定になってると、圧縮フォーマットの関係でサイズが大きくなることがあります。
なぜ?実際にブラウザで実行したらメモリ不足で落ちちゃう
Editorでは落ちないのですが、クローム上で実際に動かすとパンを数枚切ったところで落ちたり落ちなかったりしてました。
Build時に使用メモリを指定することができるので、それを増やせばいい
というような安易な解決はせず、ちゃんと原因を探りました。
容量12MBまで削減して、メモリにのるアセットも少ないはずなのになぜ落ちるのか?
Build時に使用メモリを指定することができるので、それを増やせばいい
というような安易な解決はせず、ちゃんと原因を探りました。
容量12MBまで削減して、メモリにのるアセットも少ないはずなのになぜ落ちるのか?
勘で調べるのは大変なので、もちろんUnity備え付けのプロファイラを使いました。
プロファイラをつけて実行してみると、パンを切った瞬間に60MB以上アロケートされ、即座に開放されてました。
Deep Profileをonにして実行すると、どの関数でメモリを消費してるのかもわかります。
ずばり、MeshCut.Cut関数の中でした。
ソースを読むと
_leftSide.AddTriangle( new Vector3[]{ _victim_mesh.vertices[p1], _victim_mesh.vertices[p2], _victim_mesh.vertices[p3] }, new Vector3[]{ _victim_mesh.normals[p1], _victim_mesh.normals[p2], _victim_mesh.normals[p3] }, new Vector2[]{ _victim_mesh.uv[p1], _victim_mesh.uv[p2], _victim_mesh.uv[p3] }, new Vector4[]{ _victim_mesh.tangents[p1], _victim_mesh.tangents[p2], _victim_mesh.tangents[p3] }, sub);
というコードがありました。
_victim_meshはUnityのMeshクラスです。
Meshクラスのverticesプロパティは、その見た目の印象と違い、内部の配列に直接アクセスしてるわけではなく、コピーした配列を作って返します。
Meshクラスのverticesプロパティは、その見た目の印象と違い、内部の配列に直接アクセスしてるわけではなく、コピーした配列を作って返します。
そのため、「_victim_mesh.vertices[p1], _victim_mesh.vertices[p2], _victim_mesh.vertices[p3]」の部分だけでも3回配列がコピーされて即座に捨てられるということになっています。
悪いことにこれがfor文の中にあったので、メッシュ自体は数キロバイトでも、そのコピーが1フレーム中に1000回近く生成されていました。
そこで
var mesh_vertices = _victim_mesh.vertices; var mesh_normals = _victim_mesh.normals; var mesh_uv = _victim_mesh.uv; var mesh_tangents = _victim_mesh.tangents;
というように、for文の外で変数に配列を代入して、mesh_verticesを使うよう置き換えました。
これだけでほとんど切った際にメモリを使わなくなりました。
MeshCutがオープンソースでありがたいところでした。
Unityのプロファイラはとても簡単で便利なので、それもとても助かりました。
MeshCutがオープンソースでありがたいところでした。
Unityのプロファイラはとても簡単で便利なので、それもとても助かりました。
最後に
今回は結構苦労することもなくサックり作れたのが良かったです。
こういうイベントに参加するのはいろいろと楽しいので、都合がよかったらまた出てみたいと思います。
0 件のコメント:
コメントを投稿