UE4でWindowサイズにかかわらずゲーム画面のアスペクト比を固定する方法。つまりレターボックス。

# 概要

　Windowsのゲームで画面サイズを16:9に固定して余白は黒で塗りつぶしたい。いわゆるレターボックス対応したいときの方法をメモっときます。

# DPICustumScaleを設定する

　まず最初にDPI Scalingをカスタマイズします。
プロジェクトに**DPI_CustumScalingRule**の継承クラスを作成します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147177/7e466d1b-61e0-ad93-7b6d-4a35b74967cb.png)

クラスの中身はこんな感じ。
画面サイズはとりあえず1920x1080に決め打ちです。プロジェクトに合わせて変更してください。

```MyDPICustumScalingRule.h
// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Engine/DPICustomScalingRule.h"
#include "MyDPICustomScalingRule.generated.h"

/**
 * 
 */
UCLASS()
class LETTERBOX_API UMyDPICustomScalingRule : public UDPICustomScalingRule
{
	GENERATED_BODY()
	
public:
	virtual float GetDPIScaleBasedOnSize(FIntPoint Size) const override;
};
```

```MyDPICustomScalingRule.cpp
// Fill out your copyright notice in the Description page of Project Settings.

#include "MyDPICustomScalingRule.h"

float UMyDPICustomScalingRule::GetDPIScaleBasedOnSize(FIntPoint Size) const
{
#if PLATFORM_WINDOWS
	if (Size.X > 0 && Size.Y > 0)
	{
		float ax = Size.X / 1920.f;
		float ay = Size.Y / 1080.f;

		return FMath::Min(ax, ay);
	}
#endif
	return 1.f;
}
```

　クラスができたらコンパイルして、プロジェクトに設定します。

　編集->プロジェクト設定 を開き、**User Interface**の**DPI Scaling**に設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147177/c82be066-bc5d-8486-f645-0c3bfd8b7383.png)

**DPI Scale Rule**を**Custom**
**Custom Scaling Rule Class**に作成したクラスを指定。

# カメラの設定

　レターボックス状態、余白を黒で塗りつぶした状態にするには、カメラのフラグを設定する必要があります。プロジェクト用に**GameMode**,**PlayerController**,**PlayerCameraManager**のBPクラスを作成し、ワールドセッティングに設定します。

作成したBPクラス
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147177/4da75baf-d048-b638-153a-19623171f30a.png)

World Setteingsに設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147177/c018990d-ae43-f236-cece-ac9f6f53574b.png)

作成した**PlayerContoller**の **Player Camera Manager Class**に作成した**PlayerCameraManager**を設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147177/1aed19aa-8b3e-7c26-3d67-5f0dcff5c07d.png)

**PlayerCameraManager**の **Default Constrain Aspect Ratio**にチェック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/147177/d3e75a95-e806-ffef-1f93-bb50a37583ad.png)

以上の設定でレターボックスが有効になります。
デフォルトの画面サイズを1920x1080(16:9)にしたので、画面サイズをどう変更しても、ゲーム画面は16:9になり、余白は黒で塗りつぶされます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/147177/048b94a0-3e60-e82a-891e-4aa578c7282f.png)

# UMGのアンカー問題

　これでレターボックス表示ができた！と喜んだのもつかの間、UMGのレイアウト問題が浮上します。UMGのアンカーで画面端を指定した場合、レターボックスではなく、実際の画面の端に吸着してしまいます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/147177/1287dce8-e7f1-ab2b-acf8-f90692f45264.png)

　実はこれも回避法があって、Widgetを**Add to Viewport**で画面に追加すると、画面全体からアンカーを計算します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/147177/0a5bb426-72e2-e4ae-4e74-5c4d1f74c236.png)

これを**Add to Player Screen**に変えると

![image.png](https://qiita-image-store.s3.amazonaws.com/0/147177/8795e36a-9f25-61fe-41ea-40d7ffde287f.png)

このとおり、表示範囲に吸着します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/147177/041ec571-34bb-ffb9-a6a7-935645de86a9.png)

## Add to Player Screenで解決？

　ほとんどの場合はこれで大丈夫なのですが、**Add to Player Screen**はLocal Playerが存在しないと機能しません。実際に困ったケースは、ゲームのロード画面を表示するタイミングではLocal Playerが存在せずにうまく表示されない事がありました。その時は時間がなかったのでエンジンに手を入れて無理やり対応しましたが、そういうケースもあるということを覚えて置くと良いかもしれません。