読者です 読者をやめる 読者になる 読者になる

【Unity】カメラとレイヤー

unity UnityAdventCalendar2016

はじめに

はじめまして。 カヤックのソーシャルゲーム事業部のUnityエンジニアのmadaです。
今日はUnityのカメラとレイヤーについて紹介します。
この記事はカヤックUnityアドベントカレンダー2016の3日目の記事です。

カメラについて

UnityのSceneに配置されたオブジェクトは、それを映すカメラによってGameViewに描写されます。 カメラがなければGameViewに表示されないので、シーンにカメラを配置しましょう。 (Unityで新規シーンを作成するとデフォルトでカメラも配置されます)

f:id:kayac-mada:20161202110704p:plain
上 Scene内にActiveなカメラがないので、GameViewで警告メッセージが表示されている例

f:id:kayac-mada:20161202110707p:plain
上 Scene内にActiveなカメラがあり、GameViewにオブジェクトが表示されている例

カメラは好きな数だけ追加できますが、追加すると処理が重くなります。 複数のカメラのレンダリングの順序や、スクリーン上の位置、一部を表示するなどの設定もできます。 この記事では触れていないことも詳しく書いてあるので、Unityのマニュアルも読んでみてください。

Unityマニュアル
Unityスクリプトリファレンス

f:id:kayac-mada:20161202123016p:plain:w300
上 CameraのInspectorのスクリーンショット

Projectionについて

3D空間のオブジェクトをどのように2Dのスクリーンにシミュレートするかの設定をすることができます。 UnityではPerspectiveとOrthographicの2種類が用意されています。

  • Perspective
    遠近法を用いた描写を行います。奥のオブジェクトは小さく表示されます。
    f:id:kayac-mada:20161202130432p:plain

  • Orthographic
    平行投射を用いた描写を行います。奥のオブジェクトは手前のオブジェクトと同じ大きさで表示されます。 f:id:kayac-mada:20161202130519p:plain

カメラの描写範囲の指定

カメラで描写する範囲を設定してみましょう。 3D空間を映すカメラなので、描写範囲も3D空間を表現するものです。 描写範囲をその形状から視錐台と呼ぶこともあります。 より詳しい解説は以下のマニュアルを参考にしてください。
視錐台を理解する

カメラの描写範囲の指定(XY方向)

XY方向の指定はProjectionにより名前が異なります。

  • Perspectiveの時
    Field of viewの値で垂直画角を設定できます。 Blenderの視野角設定は水平画角なのでカメラ設定を統一するときは注意が必要です。
    f:id:kayac-mada:20161202065918p:plain
    左:Field of view:60, 右:Field of view:110
  • Orthographicの時
    Sizeの値で縦に表示する視野量の半分の値を設定します。

カメラの描写範囲の指定(Z方向)

カメラの描写範囲のZ方向はnearClipPlaneまでの距離とfarClipPlaneまでの距離を設定できます。 この範囲内にあるオブジェクトのみがレンダリングの対象になります。

クリックした位置にオブジェクトを移動する例

クリックした位置にオブジェクトを移動してみましょう。 クリックした位置のWorldPositionを取得するのに Camera.ScreenToWorldPoint(Vector3 position) を利用してみます。 position.zはカメラと取得したい座標の距離を設定する必要があります。

using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    [SerializeField]
    private Camera _camera;
    [SerializeField]
    private GameObject _targetObject;

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            // 第3引数は、カメラと取得したい座標の距離を指定します
            Vector3 mousePosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 10);
            _targetObject.transform.position = _camera.ScreenToWorldPoint(mousePosition);
        }
    }
}

f:id:kayac-mada:20161202075056g:plain:w300
クリックした位置のWorldPositionを取得して、オブジェクトを移動する例
前半はカメラのProjectionをPerspective、後半はOrthographicの設定にしています。

クリックした位置のオブジェクトを取得する例

マウスでクリックした位置に描写されているオブジェクトを取得するには、
Camera.ScreenPointToRay(Vector3 position) を利用すると便利です。

using UnityEngine;

public class NewBehaviourScript : MonoBehaviour
{
    [SerializeField]
    private Camera _camera;

    void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            RaycastHit raycastHit;
            Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
            if (Physics.Raycast(ray, out raycastHit))
            {
                // 衝突したコライダーまたは Rigidbody の Transform
                Transform hitObject = raycastHit.transform;
                Debug.Log(hitObject.name);
            }
        }
    }
}

f:id:kayac-mada:20161202053457g:plain:w300
クリックしたオブジェクト名がデバッグログに表示される例

FrameDebugger

FrameDebuggerを利用すると、1オブジェクトづつ描写順を確認できるので便利です。 Unityメニューの【Window】->【FrameDebugger】をクリックし、表示されたWindow左上の【Enable】をクリックすると利用できます。

f:id:kayac-mada:20161202101835g:plain
FrameDebuggerの使用例

複数カメラの描写順

複数のカメラが設定されている場合は、低い値のdepthから高い値のdepthの順で描写されます。

レイヤー

GameObjectにはレイヤーを設定することができます。 レイヤーを分けることで、レンダリングするカメラを分けることができます。 まずは新規レイヤーを作成してみましょう。 Unityメニューの【Editor】->【Project Settings】->【Tags and Layers】をクリックし設定画面を表示します。 ここでは、RedLayerとBlueLayerを新規登録しました。

f:id:kayac-mada:20161202134151p:plain:w200

次にGameObjectにレイヤーを設定しましょう。 設定するGameObjectのInspectorの右上にLayerを設定できるメニューがあるのでクリックして設定します。

f:id:kayac-mada:20161202134932p:plain:w200

これでGameObjectにLayerを設定できました。

カリングマスク

カメラにカリングマスクを設定することで、カメラが描写するオブジェクトをレイヤー単位で指定することができます。 RedCameraは赤いオブジェクトのみ表示するように設定してみましょう。

f:id:kayac-mada:20161202194038p:plain:w250
上 カメラにカリングマスクを設定する例

実際に描写するオブジェクトをレイヤー単位で指定できているか確認してみます。

f:id:kayac-mada:20161202143805g:plain:w300
上 カメラにカリングマスクを設定した例

カリングマスクを用いて奥のオブジェクトを手前に表示する例

次の図に示した位置関係で、座標を動かさずに黒いキューブを一番手前に表示するにはどうしたら良いでしょうか?

f:id:kayac-mada:20161202145718p:plain:w300

レイヤー + カリングマスク + depthを用いることで解決できます。 複数カメラの描写順番は、カメラのdepthで設定できるので、BlackCameraのdepthを大きくします。

f:id:kayac-mada:20161202151038p:plain:w300

するとBlackCubeが一番手前に表示されるようになりました。 常に手前に表示する必要があるUIなども、この方法で設定することができます。

カメラエフェクトの紹介

Unityで用意されたカメラのエフェクトを利用すると、簡単にぼかし効果のある描写などに変更することができます。 用意されたエフェクトを利用するためには、StanderdAssetsのImportが必要で、Unityメニューの【Assets】->【ImportPackage】->【Effects】で行えます。

f:id:kayac-mada:20161202125042g:plain:w300
上 Bluerエフェクトのサンプル

おわりに

以上Unityのカメラとレイヤーについて紹介しました。 ゲーム中でどのように描写されるか描写順はどうなるか、 自分の環境でカメラの設定を変更して確かめてみると理解が深まると思います。 明日は、MonoBehaviourについての記事を書くので、引き続きよろしくお願いします。