常に全画面表示されるオブジェクトを実装する


カメラが動いても、常に全画面に表示される処理を書きます。

独自のUIなどを表示する時に使えるかもしれません。

コード

using UnityEngine;

public class FitDisplay : MonoBehaviour
{
    [SerializeField] private Transform _sprite;

    [SerializeField] private float _distance = 10; //カメラからの距離

    // spriteの一変。このsampleでは500px x 500pxの画像を表示、pixel per unit: 100なので5mの大きさになっている
    private float _spriteHeight = 5;
    private float _spriteWidth = 5;
    private Vector3 _defaultSpriteScale = Vector3.one;

    void Update()
    {
        // https://docs.unity3d.com/jp/current/Manual/FrustumSizeAtDistance.html
        // cameraから_distance手前にある時のfrustumHeightを求める
        float frustumHeight = 2.0f * _distance * Mathf.Tan(Camera.main.fieldOfView * 0.5f * Mathf.Deg2Rad);
        float frustumWidth = frustumHeight * Camera.main.aspect;
        float rateX = frustumWidth / _spriteWidth;
        float rateY = frustumHeight / _spriteHeight;

        // 画面いっぱいに広がるようにscaleを調整する
        _sprite.localScale = new Vector3(_defaultSpriteScale.x * rateX, _defaultSpriteScale.y * rateY, 0);

        Matrix4x4 viewMatInv = Camera.main.worldToCameraMatrix.inverse;
        // cameraから見た位置
        // カメラの前方は負のZ軸
        // https://docs.unity3d.com/ScriptReference/Camera-worldToCameraMatrix.html
        Vector4 viewPos = new Vector4(0, 0, -_distance, 1);
        Vector4 worldPos = viewMatInv * viewPos;
        _sprite.transform.position = worldPos;
        _sprite.transform.rotation = Camera.main.transform.rotation;
    }
}

解説

視錐台の高さを求める

まず、カメラからの距離から視錐台の高さを求めます。

求め方は公式ドキュメントにも載っています。 docs.unity3d.com

画面いっぱいになるように、scale値を調整します。

常にカメラの前に居るようにする

カメラのworldToCameraMatrixの逆変換をして、カメラの前のworld座標を求めます。

カメラ側を向くよう、回転もカメラと合わせて終わりです。