UnityのCamera.mainとは? GetComponent<Camera>()との違いを理解しよう

広告

Unityでマウス位置からRayを飛ばすコードを書いていると、次のようなコードを見かけることがあります。

Ray ray = Camera.main.ScreenPointToRay(Mouse.current.position.value);

ここで初心者の方が気になりやすいのが、

Camera.main

です。

「これは GetComponent<Camera>() と何が違うの?」

「MainCameraという名前のカメラを取っているの?」

今回は、この Camera.main の意味を整理してみます。

Camera.mainは何を取得している?

Camera.main は、シーン内にある

MainCamera タグが付いているGameObjectのCameraコンポーネント

を取得するためのプロパティです。

たとえば、Unityで最初から作成されている Main Camera を選択すると、Inspectorの上部に

Tag: MainCamera

と設定されています。

Camera.main は、このタグを手掛かりにCameraを取得します。

イメージとしては、次のような処理に近いです。

GameObject obj = GameObject.FindGameObjectWithTag("MainCamera");
Camera cam = obj.GetComponent<Camera>();

つまり、

Camera.main

と書くだけで、メインカメラの Camera コンポーネントを取得できます。

Camera.mainはMainCameraタグを手がかりにCameraコンポーネントを取得する

GameObjectの名前が「Main Camera」だからではない

ここは特に重要です。

Camera.main は、

GameObjectの名前が「Main Camera」

だから取得しているわけではありません。

確認してみましょう。

GameObjectの名前を、

Main Camera

から

MyCamera

に変更しても、

Tag: MainCamera

のままであれば、

Camera.main

で取得できます。

逆に、GameObjectの名前が

Main Camera

でも、タグを

Untagged

に変更すると、

Camera.main

では取得できません。

つまり判断基準は、

名前ではなくタグ

です。

GetComponent<Camera>()との違い

では、

GetComponent<Camera>()

とは何が違うのでしょうか。

GetComponent<Camera>() は、

このスクリプトが付いているGameObjectからCameraコンポーネントを探します。

たとえば、次のスクリプトをカメラ自身に付けたとします。

using UnityEngine;

public class CameraTest : MonoBehaviour
{
    void Start()
    {
        Camera cam = GetComponent<Camera>();
    }
}

この場合は、

CameraTest
   ↓
同じGameObject
   ↓
Cameraコンポーネント

を取得します。

GetComponent<Camera>()はスクリプトが付いているGameObjectからCameraコンポーネントを取得する

Camera.mainは別のGameObjectから取得できる

一方、

Camera.main

は、このスクリプトがどこに付いているかは関係ありません。

たとえば、

Player

にスクリプトが付いていても、

Camera cam = Camera.main;

と書けば、

Player
   ↓
MainCameraタグを探す
   ↓
Main Camera
   ↓
Cameraコンポーネント

という考え方でCameraを取得できます。

2つを比べてみる

違いを簡単に整理すると、次のようになります。

書き方 どこから探す?
GetComponent<Camera>() このGameObject
Camera.main MainCameraタグが付いたGameObject

つまり、

GetComponent<Camera>()

は

「自分が持っているCameraをください」

という処理です。

一方、

Camera.main

は

「シーンのメインカメラをください」

という処理だと考えると分かりやすいでしょう。

最初のコードをもう一度見てみよう

それでは、最初のコードに戻ります。

Ray ray = Camera.main.ScreenPointToRay(
    Mouse.current.position.value
);

まず、

Camera.main

でメインカメラを取得しています。

次に、

Mouse.current.position.value

で現在のマウスカーソルの画面上の座標を取得します。

そして、

ScreenPointToRay()

を使って、その画面上の位置を通るRayを作っています。

つまり、この1行は、

メインカメラから見て、マウスカーソルがある方向へRayを作る

という処理になります。

Camera.mainからマウス位置の方向へRayを作る流れ

処理を分けると分かりやすい

初心者のうちは、1行で書かずに分けてみるのもおすすめです。

Camera cam = Camera.main;

Vector2 mousePosition = Mouse.current.position.value;

Ray ray = cam.ScreenPointToRay(mousePosition);

こうすると、

1. Cameraを取得する
2. マウス位置を取得する
3. Rayを作る

という3段階になり、処理が見やすくなります。

「MainCameraだったらGetComponentする」と考えてよい?

学習段階では、

MainCameraタグのGameObjectを探す
        ↓
そのCameraコンポーネントを取得する

というイメージを持っておけば十分です。

たとえば頭の中では、

GameObject obj =
    GameObject.FindGameObjectWithTag("MainCamera");

Camera cam =
    obj.GetComponent<Camera>();

のような処理だと考えると理解しやすいでしょう。

ただし、実際に自分でこのコードを書く必要はありません。

Unityが用意している

Camera.main

を使えば、簡潔に書くことができます。

Camera.mainがnullになることもある

注意点もあります。

シーン内に

MainCamera

タグが付いているCameraが存在しない場合、

Camera.main

は null になります。

その状態で、

Camera.main.ScreenPointToRay(...)

を実行するとエラーになる可能性があります。

そのため、

Main Cameraを削除した
タグをUntaggedに変更した
別のCameraを作った

といった場合には、タグ設定も確認してみましょう。

まとめ

今回のポイントは次のとおりです。

Camera.main

は、

MainCameraタグが付いているGameObjectのCameraコンポーネントを取得する

ためのものです。

一方、

GetComponent<Camera>()

は、

このスクリプトが付いているGameObjectのCameraコンポーネントを取得する

ためのものです。

そして、

Ray ray =
    Camera.main.ScreenPointToRay(
        Mouse.current.position.value
    );

は、

メインカメラから見て、マウス位置の方向へRayを作る

という処理になります。

1行のコードでも、

Cameraを取得する
↓
マウス位置を取得する
↓
Rayを作る

と分解して考えると、Unityのコードはぐっと読みやすくなります。

訪問数 2 回, 今日の訪問数 2回

広告

Camera,Unity

Posted by hidepon