独習 Unity アプリ開発

独習でスマフォ向けアプリ開発を勉強中

Unity で テトリス風ゲームを作ってみる#3

Unityでゲームを作る

前回の続き


テトリミノとブロックをUnity 上でどのように表現するかは整理できたので、今回はフィールドを考える

 

フィールド


フィールド自体は縦20 ライン、横10 個の単純なマス目でそれにフィールドの上下左右に枠のブロックを1 個づつ配置したもので表現する。

パッと考えると、フィールドを2次元配列と見立てて管理することを思いつく。2次元配列の各要素が、フィールドの各マスの状態を表し、"空"の状態や、"ブロック"が置かれている状態などと表現できれば、テトリミノ (のブロック) の移動判定や接地判定ができそうだ。

ただ、せっかくUnity というゲームエンジンを使うので、2次元配列の管理方法を使わない方法で考えてみる。

必要なことは、

    • テトリミノが左右下移動、左右回転を行う際に、それぞれの移動先、回転先にブロックや枠があるかどうかを判定できること。
    • 接地したときにブロックとしてその場に留まること。(テトリミノからブロックを分離して、フィールドに配置する)
    • 1 ライン消されたときに、それより上の段にあるブロックを下段に移動すること。(上の段のブロックが検出できること)

 

移動、回転時の事前チェック

Unity で特定の場所にブロック(GameObject)があるかどうかを判定する方法には、ColliderRaycast という仕組みで実現可能である。
Collider はGameObject を衝突判定対象に加えるコンポーネントで、Raycast はCollider コンポーネントを検出することができる仕組のこと。Raycast は名前のとおり、特定の場所から特定の方向、特定の長さの見えないレーザーを発射して、レーザーがどのCollider 付きGameObject に当たったかを検出できる。

つまり、それぞれのブロック(GameObject)にCollider コンポーネントを付けて、移動イベント、落下イベント、回転イベントが発生したときに、その移動先にRaycast を打って他のブロックがあるかどうかを確認することで移動や回転が可能かの事前チェックができる。

 

プロト実装してみた結果が下記。赤いブロックが下に落下するときにRaycast を下向きに1 ブロック分の長さで発射して、緑のブロックのCollider を検出したら止まるようになっている。

実装は、Monobehaviour コンポーネントC#スクリプトを記述できるコンポーネント)を使って実現しているが、詳細は実装編にて説明。

www.youtube.com

ブロックのあたり判定方法をどうするか決まったので、あとは同様の仕組みでフィールド(の外枠)を実現すればよい。

 

フィールドと表示サイズ


フィールドは、単に20 ラインx10 個のスペースとその外側にブロックを配置することで表現する。

ところが、何も考えず、ブロックを縦横に並べると下図のようにフィールドの左下の一部だけがゲーム画面上に表示されてしまう。(画面の領域外にもちゃんと20 ライン x 10 個の外周にブロックが並んでいるが、画面外なので見えていない)

 

ここで重要になっていくるのが、カメラの設定とUnit 単位の整理。

 

カメラとUnit単位


Unity には (というか一般的な3D Game Engine には)、カメラという概念が存在する。Unity 内のカメラでScene(ゲームの仮想3D 空間)を撮影し、その撮影されたゲーム画面を実際のディスプレイ(特定のPixcelサイズを持った2D 平面)上に投影する。これは3D ゲームだけでなく2D ゲームであっても同様(2D ゲームの場合は、仮想3D 空間をOrthographic という方式の投影方法でカメラ撮影した結果)。

つまり、Scene をどの角度からどのくらいの距離でカメラ撮影をするかによって、最終的にディスプレイにどのように表示されるかが変わることになる。

 

カメラとDisplay

 

カメラは、Unity でプロジェクトを作成すると自動的に1個生成されている(Main Cameraという名前のGame Object)。これとは別に後から自分で複数のカメラを生成することで、ディスプレイに表示するカメラ映像を切り替えたり、車のバックミラーを実現するために車の後方を撮影したカメラ画像を特定領域に縮小して埋め込んだりするような使い方もできる。

 

Camera Object

 

2D ゲームの場合、調整するカメラのパラメータは、Camra GameObject の位置 (TransformのPosition)と画角サイズ (OrthographicSize)。 2D ゲームではProjection(投影方法)は通常Orthographic 方式を選択することになる(プロジェクト作成時に2D ゲームを選択していれば、デフォルトでOrthographic になっている)。このためZ軸方向はあまり深く考えなくてもOKで、デフォルトの値(-10)のままで問題ない。(Orthographic 方式の場合、Z 軸方向をいくら動かしてもキャラクタの見え方は変わらない)

Orthographic 投影の場合、カメラ位置以外にディスプレイ上の見え方に関係するのが、Unit を何Pixel とするかである。なぜならカメラの画角サイズ(ディスプレイに表示する範囲)を決めるOrthographicSize の値は、カメラ画角サイズの高さの1/2が何Unit かで定義される値のため。例えばデフォルト値のOrthographicSize = 5 とは、カメラ画角の高さの1/2が5 Unit であることを意味している(= ディスプレイの高さの1/2が5 Unit 分)。

Unit とは、Unity 内で使われる長さの単位であり、1 Unitは1 mを表している(確か)。3D ゲームでは現実世界をモデリングして配置した仮想空間として作られることが多いため、モデルも含めオブジェクトのサイズや距離はメートル単位で表現される。

しかし、2D ゲームの世界だと(特に今回作ろうとしているテトリス風ゲームでは)、ブロックが実際何メートルなのかとかはあまり関係がない。ではどうやって決めるかというと、使用するテクスチャのPixel数を基準に考える。1 Unit を何Pixel とするか、もしくは逆に1 Pixel を何Unit にするかを決めてあげればOK。

もちろん、1 Unit = 1 Pixel とかでもよい (その分カメラ画角を大きくしないと画面に収まりきらないが)。

 

テクスチャ画像を1 Unit あたり何pixcel とするかは、テクスチャのSprite Mode 設定の"Pixels Per Unit"に値を設定することで決まる。例えば下記の例だとブロックのテクスチャは、1 Unit = 128 Pixcel と設定されていることになる。

テクスチャ設定

この設定のまま、Scene に上記のテクスチャを使ったブロックのGameObjectを配置してみると、Scene のグリッドのマス目にピッタリ一致するサイズであることが確認できる。これはScene のグリッドは1Unit 単位で引かれているためである(最大限に拡大したときに見えるマス目)。

 

シーンビュー上のブロック

 

今度は同じテクスチャを 1 Unit = 1Pixel に設定を変えて、同じScene 上に配置してみると、下記のようにかなり大きく表示されることになる(全体が収まっていないが、ブロックの左上の部分が見えている)。

大きくなるといっても、結局カメラの画角(OrthographicSizeの値)を大きくしてしまえば、ディスプレイ上の見た目はどちらも同じにすることはできる。

シーンビュー上のブロック(1 Unit = 1Pixel)

 

もう一点、Unit とPixel の関係で重要な要素がある。GameObject のTransform のPosition とScale の制御方法である。Transform のPosition とScale の単位はPixel ではなくUnit である。例えば、Position X を +1 した場合は、1 Pixel 右に移動するわけではなく、1 Unit 右に移動することを意味している。(親Objectがある場合は別の話があるが)

 

Transform


ブロックのテクスチャが128 x 128 Pixel で描かれており、1 Unit = 128 Pixel と設定した場合、1 ブロック分右に移動するといった制御をする場合は、TransformのPosition.x を +1すればよいが、1 Unit = 1 Pixelとした場合は、+ 128する必要がある。
プログラム上どちらがやりやすいかは人それぞれかと思うが、将来テクスチャの解像度を変更することになった場合、プログラム内で 128 基準で計算している箇所も併せて修正する必要が出てくる(もちろんどこか一か所で定義しておけばよいだけではあるが)

 

今回は、1 Unit = 128 Pixel として進める。

PixelとUnit

今回のゲーム画面では、フィールドはブロック20 個分で、そこに枠ブロックが1個あり、さらに上下にある程度の余白を持たせるとすると、必要なOrthograpicSize は下記のように計算される。

OrthographicSize/Offsetの計算

 

上記の計算結果をCamera/ブロック位置に反映すると、下図のように正しく表示ができた。

Field配置

 

次の記事


Unity で テトリス風ゲームを作ってみる#4

 

 


目次に戻る