これはなに
Unity の FieldOfView は垂直方向の視野です。
よって、 ScreenOrientation.AutoRotation などに対応する場合、 Landscape にしたとき対象物が小さく見えます。
iPhone 4 Tall (640x940) / Wide (940x640)
これが、同じ大きさに見えるように、 FieldOfView を調整するスクリプトを書きました。
スクリプト
Camera と同じ GameObject に挿してください。
毎フレーム更新しちゃう版
FixFieldOfViewOrientation.cs
using UnityEngine;
[RequireComponent(typeof(Camera)), ExecuteInEditMode]
public class FixFieldOfViewOrientation : MonoBehaviour
{
[SerializeField, HideInInspector] private Camera _camera;
[Range(1, 179)] public float fieldOfView;
private bool IsLandscape => _camera.aspect > 1;
void Update()
{
_camera.fieldOfView = FixedFieldOfView(fieldOfView, _camera.aspect, IsLandscape);
}
private static float FixedFieldOfView(float fieldOfView, float aspect, bool isLandscape)
{
if (isLandscape) return fieldOfView / aspect;
return fieldOfView;
}
void OnValidate()
{
_camera = GetComponent<Camera>();
}
}
- EditMode で動く
- Camera.fieldOfView set でなにをやってるかわからないので、毎フレーム呼んで大丈夫かがほんの少しだけ不安
Camera.fieldOfView を無駄に更新しない版
FixFieldOfViewOrientation.cs
using UniRx;
using UnityEngine;
[RequireComponent(typeof(Camera))]
public class FixFieldOfViewOrientation : MonoBehaviour
{
[SerializeField, HideInInspector] private Camera _camera;
[Range(1, 179)] public float fieldOfView;
private bool IsLandscape => _camera.aspect > 1;
void Start()
{
Observable.EveryUpdate()
.Select(_ => FixedFieldOfView(fieldOfView, _camera.aspect, IsLandscape))
.DistinctUntilChanged()
.Subscribe(x => _camera.fieldOfView = x)
.AddTo(this);
}
private static float FixedFieldOfView(float fieldOfView, float aspect, bool isLandscape)
{
if (isLandscape) return fieldOfView / aspect;
return fieldOfView;
}
void OnValidate()
{
_camera = GetComponent<Camera>();
_camera.fieldOfView = FixedFieldOfView(fieldOfView, _camera.aspect, IsLandscape);
}
}
- EditMode で画面サイズ変えても反映されない
- ほしければ、 Rx 使わないで普通に Update で前フレームとの比較書けばいいと思う
- Camera.fieldOfView set を無駄に叩かない
補足など
Camera は sealed class なので継承で解決できません。
今回のケースに限っては継承したほうがエレガントに解決できそうな気もしましたが、いずれにせよ、です。
外部のスクリプトから変更する場合など、こちらのコンポネントを経由するように注意する必要があります。
Camera.fieldOfView を自分が更新したのか、外部から更新されたのかをがんばって判別してゴニョゴニョするほどではないかなと思ってやっていません。
そもそも Camera.fieldOfView set に関しては、一応気にしてみましたが、恐らく問題ないと思うので、基本的には上を使うで良いと思います。たぶん。
ちなみに uGUI は、 Canvas Scaler を用いて類似の問題を解決できます。
Unity - マニュアル: 複数の解像度のための UI 設計
それでは、レッツ複数解像度対応!!