【Unity】カメラ制御とアドバンスドカラーマネージメント

Unity

Unityでのカラーマネージメントとカメラ制御は、任意のシーンをリアルタイムで豊かに表現する上で重要な役割を果たします。この記事では、カメラの制御方法、リアルタイムグローバルイルミネーション(GI)の設定について深く掘り下げます。

今回の記事の手順を踏んで作成したいものは下記↓

カメラ制御

まずは、画面をドラッグした状態でマウスを動かした時にカメラが動くように設定していきます。

スクリプトの作成(CameraController.cs)

今回は「CameraController.cs」という名前のスクリプトを作成します。具体的なスクリプトの中身は下記です。

using UnityEngine;
using UnityEngine.EventSystems; // EventSystemの名前空間を追加
using System.Collections.Generic; // リストを使用するため

public class CameraController : MonoBehaviour
{
    public Camera controlledCamera; // 制御するカメラ
    public GameObject targetObject; // 中心にするオブジェクト
    public float zoomSpeed = 10f; // ズームの速度
    public float minZoomDistance = 10f; // 最小ズーム距離
    public float maxZoomDistance = 100f; // 最大ズーム距離
    public float rotationSpeed = 5f; // 回転の速度
    public float minXRotation = 0f; // X軸方向の最小回転角度
    public float maxXRotation = 45f; // X軸方向の最大回転角度

    private float currentZoomDistance;
    private Vector3 originalCameraPosition;
    private Quaternion originalCameraRotation;
    private float currentXRotation = 0f; // 現在のX軸回転角度

    void Start()
    {
        originalCameraPosition = controlledCamera.transform.position;
        originalCameraRotation = controlledCamera.transform.rotation;
        currentZoomDistance = Vector3.Distance(controlledCamera.transform.position, targetObject.transform.position);
        currentXRotation = controlledCamera.transform.eulerAngles.x;
    }

    void Update()
    {
        HandleZoom();
        if (!IsPointerOverUIObject()) // UIオブジェクト上にない場合のみ実行
        {
            HandleRotationAroundObject();
        }
    }

    void HandleZoom()
    {
        float scroll = Input.GetAxis("Mouse ScrollWheel");
        currentZoomDistance = Mathf.Clamp(currentZoomDistance - scroll * zoomSpeed, minZoomDistance, maxZoomDistance);
        controlledCamera.transform.position = targetObject.transform.position - controlledCamera.transform.forward * currentZoomDistance;
    }

    void HandleRotationAroundObject()
    {
        if (Input.GetMouseButton(0)) // 左クリックで回転
        {
            float horizontalRotation = Input.GetAxis("Mouse X") * rotationSpeed;
            float verticalRotation = -Input.GetAxis("Mouse Y") * rotationSpeed;

            // X軸回転を制限
            currentXRotation = Mathf.Clamp(currentXRotation + verticalRotation, minXRotation, maxXRotation);
            verticalRotation = currentXRotation - controlledCamera.transform.eulerAngles.x;

            // カメラの回転を制御
            controlledCamera.transform.RotateAround(targetObject.transform.position, Vector3.up, horizontalRotation);
            controlledCamera.transform.RotateAround(targetObject.transform.position, controlledCamera.transform.right, verticalRotation);
        }
    }

    bool IsPointerOverUIObject()
    {
        PointerEventData eventDataCurrentPosition = new PointerEventData(EventSystem.current);
        eventDataCurrentPosition.position = new Vector2(Input.mousePosition.x, Input.mousePosition.y);
        List<RaycastResult> results = new List<RaycastResult>();
        EventSystem.current.RaycastAll(eventDataCurrentPosition, results);
        return results.Count > 0;
    }
}

このスクリプトは、以前の記事で作成した「UIManager」オブジェクトにドラッグ&ドロップでアタッチすると、UIManagerのインスペクタウィンドウに項目が表示されるので、項目に対応するオブジェクトや値を設定しましょう。

カメラ設定のインスペクタウィンドウの見方

リアルタイムGIの設定

次に、エミッションスライダーを調節してオブジェクトが光っている時に、周辺のオブジェクトに対して自然な光方の影響が出るように設定していきます。オブジェクトが光る(エミッションを持つ)場合、その光がオブジェクトの周辺環境に影響を与えるためには、リアルタイムグローバルイルミネーション(GI)を有効にする必要があるため、その設定になります。

スクリプトの作成(EmissionController.cs)

今回は「EmissionController.cs」という名前のスクリプトを作成します。具体的なスクリプトの中身は下記です。この新しいスクリプトは、エミッション値が変更された際に「CubeColorManager.cs」から選択されたRendererを取得し、DynamicGIを更新します。

using UnityEngine;
using UnityEngine.UI;

public class EmissionController : MonoBehaviour
{
    public Slider emissionIntensitySlider; // エミッション強度を調整するためのスライダー
    public CubeColorManager cubeColorManager; // CubeColorManagerへの参照
    public Slider hueSlider; // 色相スライダーへの参照

    void Start()
    {
        emissionIntensitySlider.onValueChanged.AddListener(HandleEmissionChange);
    }

    void HandleEmissionChange(float intensity)
    {
        // 色相スライダーの値に基づいてエミッションカラーを計算
        Color emissionColor = Color.HSVToRGB(hueSlider.value, 1.0f, 1.0f) * intensity;

        Renderer selectedRenderer = cubeColorManager.SelectedCubeRenderer;
        if (selectedRenderer != null)
        {
            Material mat = selectedRenderer.material;
            mat.EnableKeyword("_EMISSION");
            mat.SetColor("_EmissionColor", emissionColor);
            DynamicGI.SetEmissive(selectedRenderer, emissionColor);
        }
    }
}

このスクリプトも、以前の記事で作成した「UIManager」オブジェクトにドラッグ&ドロップでアタッチすると、UIManagerのインスペクタウィンドウに項目が表示されるので、項目に対応するスライダーを設定しましょう。(※今回のコードにおいて対応するスライダーとは、以前の記事で作成した「Slider Emission(エミッションスライダー)」「Slider H(色相スライダー)」の2つです。)

Lighting Settingの変更

それでは次に、リアルタイムGIを有効にするための設定をUnity上で実施していきます。

リアルタイムGIとは?

リアルタイムグローバルイルミネーション(Real-Time Global Illumination、略してリアルタイムGI)は、ゲームやシミュレーション内で光の挙動をより現実的に再現する技術です。この技術を使うことで、光がオブジェクトに当たった後に他の面に反射する様子(間接光)をリアルタイムで計算し、シーン全体の照明をより自然に見せることができます。

環境の質の向上: リアルタイムGIを使うと、ゲーム内の環境がよりリアルで没入感のあるものになります。
動的な光の変化: 光源の位置や強さが変わると、それに応じてシーンの照明もリアルタイムで変化します。これは、昼夜のサイクルや天候の変化など、動的なシーンで特に効果的です。

Unity上で、リアルタイムGIを有効にする具体的な手順は、下記の記事の「オブジェクトをStaticに変更」「Lighting Settingの変更」で紹介している手順を参考にしてください。

作成結果の確認

今回はカメラの制御、リアルタイムGIの設定をしました。実際にシーンを再生してみると、今回設定した範囲内でカメラが動くことが確認できました。また、リアルタイムGIを使う以前に比べてエミッション(発光)の効果がよりわかりやすくなったかと思います。

まとめ

本記事を通じて、Unityにおけるカメラ制御やアドバンスドカラーマネージメントの重要性とその設定方法を詳しく解説しました。これらの技術を駆使することで、開発者はリアルタイムでダイナミックなビジュアルエフェクトを作成し、ユーザーに圧倒的なビジュアル体験を提供することが可能になります。

コメント