チワ裏

とあるゲーム作りたい人のチラシの裏

開発日記 その3 巨大な迷路を3Dオブジェクトで表現する

第三回です。
意外と順調に更新ができているので自分でも驚きです。

さて、今回は1000*1000の迷路を3Dオブジェクトで表現する方法について書いていきます。

方法1 1000*1000個のゲームオブジェクトを用意する!

結論から言って無理です。
流石にこんな阿呆な実装をする人はいませんが、いちおう試して消費メモリを計測してみました。
f:id:tiwaluna:20171205210014p:plain

1.54GBになります。デデドン(絶望)
ちなみに本当に1000*1000個の生成をするとゲーム自体が起動しなかったので、上のスクショは500*500=250000個のゲームオブジェクトの生成したときの結果です。

想像通りの結果ですね。

目標のメモリ消費量

256MBです。
理由として、WebGLでゲームを作る際にこんな設定があります。 (ProjectSettings->Player->WebGL)
f:id:tiwaluna:20171205210901p:plain

ここで設定する値がブラウザ上で確保されるメモリ量だと思われます。256MBより多く設定すると32bit環境で動かないなどという警告がでますね。
なので超軽量なUnityゲームのメモリ消費量は256MB以下なんじゃないかなーと思ってます。
今回はカジュアルに遊べるようなスマホゲームを目指しているので目標はこれぐらいを目指しています。
Unity - マニュアル: WebGLを対象とした場合に必要なメモリへの配慮

方法2 オブジェクトプールの考え方を用いる

オブジェクトプールとは、単純にいうとオブジェクトを使いまわすことです
具体的には、初めに十分な数のオブジェクトを用意しておいて、アクティブと非アクティブの切り替えを行うことをします。
これにより、毎回DestroyやInstantiateをすることがなくなるので効率化することが可能です。

また、使いまわすという考え方を応用して、以下のような方法を考えます。
f:id:tiwaluna:20171205212934p:plain

この考え方を用いると、カメラの視界に収まる数のオブジェクトのみで迷路のフィールドを表現することが可能です。

まず、カメラの視界内に収まる十分な量のオブジェクトを生成します。今回は10*10個用意しました。
プレイヤーが右に動いた場合、左端の列が視野外に出ます。また、右端の列にオブジェクトが表示されていない状態になります。
ここで、図に示したように、左端の列を右端に移動することによってグラフィックが途切れないようにすることが可能です。
その他の方向についても同様になります。

続いて、迷路の壁の表現について考えます
今回のゲームではいわゆる「壁マス」というものは存在せず、マスとマスの間に壁が存在します。
壁がどこに存在するかについては、マスごとに判定しています。
各マスごとに壁のある方向、「下」または「右」を設定して壁を作っています。
ここで、オブジェクトプールの考え方を利用して、あらかじめ下と右方向の壁を用意しておきます。
各マスの壁の方向をデータで保持して、必要に応じて表示、非表示を切り替えていきます。
図にすると以下のようになります。
f:id:tiwaluna:20171205214411p:plain

これらの考え方を利用すると、オブジェクト数が、3 * 10 * 10 = 300個で済みます。
データは
GameObject配列 [300]
方向用データ [1000 * 1000]
になりました。今回のゲームでは方向のデータをビットフラグを利用してint型1つで表現しています。

最後にメモリ消費量の測定結果です。
f:id:tiwaluna:20171205214748p:plain

約63MBに削減できました。
これから色々な要素を詰め込んでいきたいのでこの軽量さはとてもうれしいですね。

おわりに

実際に動かした結果

わざとオブジェクトの移動が見えるようにしていますが、実際にはカメラの視界やマスの大きさを調整することで自然な感じにできます。

今回はここまで。
過去最高の文字数の記事になったかも。

ようやくアルゴリズムの改善方法がまとまってきたので、次回はアルゴリズムの紹介をしたいと思います。