Unity2Dで画面のアスペクト比を固定にしたい【Unity】


2Dゲームを作っている時に色んなデバイスで画面サイズを背景に合わせたい時があったのでメモ。

- 背景にサイズを合わせたい
- アスペクト比は固定にしたい
- 背景からはみ出す部分は黒くしたい
- デバイスのスクリーンサイズから縦に合わせるか横に合わせるかを判断してアスペクト比を固定で表示させたい


## 今回使用する画像
これのアスペクト比を保ったまま表示させたいです。
640×960 の縦長の画像
<img src="https://qiita-image-store.s3.amazonaws.com/0/29966/cd1e292c-f081-94d8-b351-ea17208ae8df.png" alt="bg_vertical.png" width="200" />

## 配置
そのまま配置しただけなので当然画面と合わないです。
<img src="https://qiita-image-store.s3.amazonaws.com/0/29966/e5cf2751-194a-cb3c-6e22-7d13b49ca0d5.png" alt="スクリーンショット 2015-07-24 21.55.02.png" width="500" />

## 縦にフィットさせる
画面サイズを画像の縦サイズにフィットさせるスクリプトを用意してカメラにアタッチします。
カメラの[orthographicSize](http://docs.unity3d.com/ja/current/ScriptReference/Camera-orthographicSize.html)がカメラの縦幅の半分なので、そこに画像サイズをpixle per unitで割った値を入れます。

```C#:StableAspect.cs
private Camera cam;
// 画像のサイズ
private float width = 640f;
private float height = 960f;
// 画像のPixel Per Unit
private float pixelPerUnit = 100f;

void Awake () {
	// カメラコンポーネントを取得します
	cam = GetComponent<Camera> ();
	// カメラのorthographicSizeを設定
	cam.orthographicSize = height / 2f / pixelPerUnit;
}
```

画面の縦サイズにフィットしました。
<img src="https://qiita-image-store.s3.amazonaws.com/0/29966/fc373527-dd01-29d0-0200-f59e719d7934.png" alt="スクリーンショット 2015-07-25 1.33.51.png" width="500" />

## 横の余白を切り取る
まだ両サイドの余白が丸見えなので、これをマスクする形で隠します。
Cameraの[viewport rect](http://docs.unity3d.com/ja/current/ScriptReference/Camera-rect.html)が画面内のどこに描画されるかを設定するプロパティなので、それを設定します。
それにしてもinspector上のプロパティ名とスクリプトで名前が違うのはなんでなのでしょうか。

```C#:StableAspect.cs
private Camera cam;
// 画像のサイズ
private float width = 640f;
private float height = 960f;
// 画像のPixel Per Unit
private float pixelPerUnit = 100f;

void Awake () {
	// カメラコンポーネントを取得します
	cam = GetComponent<Camera> ();
	// カメラのorthographicSizeを設定
	cam.orthographicSize = height / 2f / pixelPerUnit;

	// 縦幅の倍率
	float bgScale = height / Screen.height;
	// viewport rectの幅
	float camWidth = width / (Screen.width * bgScale);
	// viewportRectを設定
	cam.rect = new Rect ((1f - camWidth) / 2f, 0f, camWidth, 1f);
}
```

このviewport rectが結構曲者で、0から1の値に正規化されています。
横幅を合わせるだけなので、width / Screen.widthでフィットしそうな気がするんですが、それではだめです。
画像の縦幅が画面サイズに合わせてスケールしているため、そのスケールの割合を加味する必要があります。
それがbgScaleです。
<img src="https://qiita-image-store.s3.amazonaws.com/0/29966/da525130-dac2-91c2-9380-8ef12cce8907.png" alt="スクリーンショット 2015-07-25 1.53.44.png" width="500" />

## 縦だけでなく横にもフィットさせる
横方向も加味します。

```C#:StableAspect.as
private Camera cam;
// 画像のサイズ
private float width = 640f;
private float height = 960f;
// 画像のPixel Per Unit
private float pixelPerUnit = 100f;

void Awake () {
	float aspect = (float)Screen.height / (float)Screen.width;
	float bgAcpect = height / width;

	// カメラコンポーネントを取得します
	cam = GetComponent<Camera> ();
	// カメラのorthographicSizeを設定
	cam.orthographicSize = (height / 2f / pixelPerUnit);


	if (bgAcpect > aspect) {
		// 倍率
		float bgScale = height / Screen.height;
		// viewport rectの幅
		float camWidth = width / (Screen.width * bgScale);
		// viewportRectを設定
		cam.rect = new Rect ((1f - camWidth) / 2f, 0f, camWidth, 1f);
	} else {
		// 倍率
		float bgScale = width / Screen.width;
		// viewport rectの幅
		float camHeight = height / (Screen.height * bgScale);
		// viewportRectを設定
		cam.rect = new Rect (0f, (1f - camHeight) / 2f, 1f, camHeight);
	}
}
```

<img src="https://qiita-image-store.s3.amazonaws.com/0/29966/5bda6df8-e3c4-dd4d-246f-0cae12ffd34d.png" alt="スクリーンショット 2015-07-25 10.44.38.png" width="500" />

Updateにこの処理を書けば、リアルタイムでのリサイズにも対応できます。
![StableAspect.gif](https://qiita-image-store.s3.amazonaws.com/0/29966/862375ce-7856-7987-b811-8a08dd36e026.gif "StableAspect.gif")