【Unity】全スマートフォン、全解像度で完全同じ画面を再現する

Unity
スポンサーリンク

Unityで開発するアプリの解像度が変わる時、カメラやキャンバス内の配置が若干変わってしまい思った通りに配置されないことがあったので今回その対策をいれてみました。

見た目の挙動

画面のサイズを変更するとこのように変化します。
キチッとゲームの画面比率やUIの位置・サイズが変わらず維持できていますね。

この対応を入れておかないと、幅が長いスマホなどで本来カメラ外の見えてはいけないモノが見えてしまったり、端末毎に操作感が変わってしまうので調整に大変苦労します。

もちろん一部画面外が黒く塗りつぶされていて画面を活かしきれてない感はあるのですが、そもそもスマホによっては見えてはいけないもの(例えばイベントが起きる前でキャラが消えてるとか)が見えてるのは論外です。

アスペクト比が違う画面などでも調整不要なこの機能を入れて楽をしてしまいましょう!

参考サイト

こちらのサイトを参考しました。

Unity2Dで画面のアスペクト比を固定にしたい【Unity】 - Qiita
2Dゲームを作っている時に色んなデバイスで画面サイズを背景に合わせたい時があったのでメモ。 背景にサイズを合わせたい アスペクト比は固定にしたい 背景からはみ出す部分は黒くしたい デバイスのスクリーンサイズから縦に合わせるか横に合...
【Unity】画面アスペクト比を画面の高さに自動的に合わせて調整する
Unityで画面アスペクト比を固定する方法は割と紹介されていますが、基本はアスペクト比を固定しつつも縦側の解像…

ただこれだけだとCanvasScalarなどを使ってもいつも同じUI位置やサイズが維持できないためプラスアルファその辺りも対応しています。

 

実装内容

おおまかな流れとしてはスクリプト2種類用意して
各オブジェクトに設定していく流れとなります。

カメラ(Camera)

カメラに対して、下記のスクリプトをアタッチします。
詳細な説明は省きますが、おおまかに説明すると

変更されたアスペクトの縦と横どちらが大きいか判別して
カメラの描画領域を調整しています。

これをゲームで使っているカメラに設定追加してください。

 

スクリプト内容

refCameraに使用するカメラコンポーネント、widthに基本解像度の幅、heightに基本解像度の高さ、pixelPerUnitについてもCanvasなどと統一した値を利用してください。

CameraStableAspect.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[ExecuteInEditMode()]
[RequireComponent(typeof(Camera))]
public class CameraStableAspect : MonoBehaviour
{
    [SerializeField]
    Camera refCamera;

    [SerializeField]
    int width = 1920;

    [SerializeField]
    int height = 1080;

    [SerializeField]
    float pixelPerUnit = 100f;


    int m_width = -1;
    int m_height = -1;

    void Awake()
    {
        if( refCamera == null ){
            refCamera = GetComponent();
        }
        UpdateCamera();
    }

    private void Update()
    {
        UpdateCameraWithCheck();
    }

    void UpdateCameraWithCheck()
    {
        if(m_width == Screen.width && m_height == Screen.height){
            return;
        }
        UpdateCamera();
    }

    void UpdateCamera()
    {
        float screen_w = (float)Screen.width;
        float screen_h = (float)Screen.height;
        float target_w = (float)width;
        float target_h = (float)height;

        //アスペクト比
        float aspect =  screen_w / screen_h;        
        float targetAcpect = target_w / target_h;
        float orthographicSize = (target_h / 2f / pixelPerUnit);

        //縦に長い
        if (aspect < targetAcpect)
        {
            float bgScale_w = target_w / screen_w;
            float camHeight = target_h / (screen_h * bgScale_w);
            refCamera.rect = new Rect( 0f, (1f-camHeight)*0.5f, 1f, camHeight);
        }
        // 横に長い
        else
        {
            // カメラのorthographicSizeを横の長さに合わせて設定しなおす
            float bgScale = aspect / targetAcpect;
            orthographicSize *= bgScale;

            float bgScale_h = target_h / screen_h;
            float camWidth = target_w / (screen_w * bgScale_h);
            refCamera.rect = new Rect( (1f-camWidth)*0.5f, 0f, camWidth, 1f);
        }

        refCamera.orthographicSize = orthographicSize;

        m_width = Screen.width;
        m_height = Screen.height;
    }
}

次はCanvas側の対応をしていきます。

1+

コメント

  1. うなぎ より:

    神スクリプトをありがとうございます!
    とっっっても助かりました!

    0
  2. Tomo より:

    とても助かります!
    ありがとうございました!
    RectScalerWithViewport.csをアタッチする場所がよく分からなかったのですが、キャンバス内に空のゲームオブジェクトを作成してそこにアタッチすればいいんですか?

    0
    • Tadashi Tadashi より:

      助けになったようで良かったです!
      下記回答となります。

      はい、RectScalerWithViewport.csはゲーム上でお使いのCanvasを親として
      その一つ下の階層にゲームオブジェクト(記事で説明しているPanel)を追加し、そこにRectScalerWithViewportスクリプトをアタッチします。

      その追加したゲームオブジェクトはRectTransformと呼ばれるCanvasの子どもになるためのオブジェクトとして作成されますので、そのRectTransformプロパティはCanvasのサイズに連動するように中心を原点とした完全フィット設定にしてください(上下左右のサイズは完全連動、原点を中心にする設定です)。

      そしてPanelで追加すると不要なImageコンポーネントが付いてきますのでこれを削除してください。

      最後にこれまでCanvas直下にあったUIなどのゲームオブジェクトをその追加したPanel(改名推奨、例:ScalerPanelなど)に全てドラッグ&ドロップで移動させます。

      少々初歩的な部分などを端折っている点もありますので
      気になることなどありましたらお気軽にご連絡ください~!

      追伸:ゲーム上でCanvasが複数ある場合、毎回対応入れないといけないのでPrefabしておくと便利です。

      0
スポンサーリンク
タイトルとURLをコピーしました