5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Unity】モバイル端末スペックを判定するロジック

Last updated at Posted at 2026-02-06

Unityでのスマホゲーム開発において、「端末のスペックに合わせて画質を自動調整したい」というのは永遠の課題です。

単純にメモリ量(RAM)だけで判定すると、「メモリは多いけどGPUが弱いAndroidタブレット」でカクついたり、「メモリは少ないけど超高性能なiPhone」で低画質判定されたりと、事故が多発します。

今回は、これらの落とし穴(メモリ詐欺など)を考慮した、5段階の自動スペック判定ロジックを紹介します。

この記事で実現すること

  • CPU性能は無視する(あてにならないため)
  • Androidの「メモリ詐欺」対策(メモリ8GBでもGPUが弱ければ低画質にする)
  • iOSの「高効率」対応(メモリが少なくても高画質判定にする)
  • 5段階評価(VeryLow / Low / Medium / High / Ultra)で判定結果を返す

なぜCPUを見ないのか?

SystemInfo.processorFrequency などでCPU情報を取得することは可能ですが、スマホ開発では推奨されません。

  1. Androidの仕様: 正確なクロック数が取得できず「0」が返ってくることが多い。
  2. SoCの構造: スマホのチップ(SoC)はCPU/GPU/メモリがセットです。「GPUとメモリが優秀なら、CPUも間違いなく優秀」という相関関係があるため、CPUを個別にチェックする必要はありません。

判定の落とし穴と対策

1. Android:メモリは多いけどGPUが弱い(通称:中華タブレットの罠)

格安のAndroidタブレットなどには、カタログスペックを良く見せるために RAM 8GB を積んでいるものの、GPU性能はiPhone 7以下……という機種が存在します。
これをメモリ量だけで「Ultra(最高画質)」と判定すると、ゲームがカクカクになります。

対策:
「GPUの性能(GraphicsTier)」を見て、画質ランクに上限(キャップ)を設けます。

2. iOS:メモリは少ないけど超高性能

iPhoneはOSのメモリ管理が優秀なため、Androidと同じ基準(4GBは低スペック扱いなど)を適用すると、iPhone 12などの高性能機まで低画質にされてしまいます。

対策:
iOSの場合は判定基準のボーダーラインを大幅に下げます。


実装コード

このクラスをプロジェクトに追加し、起動時(Awakeなど)に DetermineQualityTier() を呼ぶだけで、最適なランクが返ってきます。

PerformanceManager.cs
using UnityEngine;
using UnityEngine.Rendering;

/// <summary>
/// 端末のハードウェア性能を判定し、適切な画質ランクを返すクラス
/// </summary>
public static class PerformanceManager
{
    // クオリティの5段階定義
    public enum QualityTier
    {
        VeryLow = 0, // 最低:影なし、解像度ダウン(緊急避難用)
        Low = 1,      // 低:標準シェーダー、影簡易
        Medium = 2,   // 中:標準的な画質
        High = 3,     // 高:ポストプロセスあり
        Ultra = 4     // 最高:フルオプション
    }

    /// <summary>
    /// 端末スペックから適切なQualityTierを判定して返す
    /// </summary>
    public static QualityTier DetermineQualityTier()
    {
        int systemMemory = SystemInfo.systemMemorySize;   // メモリ (MB)
        GraphicsTier graphicsTier = Graphics.activeTier;  // GPU性能 (Tier1~3)
        bool isIos = Application.platform == RuntimePlatform.IPhonePlayer;

        // =========================================================
        // 1. GPU性能による「上限キャップ」を決める (Androidのメモリ詐欺対策)
        // =========================================================
        QualityTier maxAllowedTier;

        if (graphicsTier == GraphicsTier.Tier1)
        {
            // GPUが弱い(Tier1)なら、メモリがどれだけあっても「Low」までしか許さない
            // これにより、メモリだけ大量に積んだSoCの弱い格安端末を弾く
            maxAllowedTier = QualityTier.Low;
        }
        else if (graphicsTier == GraphicsTier.Tier2)
        {
            // GPUが並(Tier2)なら、最高画質(Ultra)は禁止し「High」で止める
            // ※Tier2の範囲は広いため、安全側に倒すなら Medium にキャップしても良い
            maxAllowedTier = QualityTier.High; 
        }
        else // Tier3
        {
            // GPUが最強(Tier3)なら上限なし
            maxAllowedTier = QualityTier.Ultra;
        }

        // =========================================================
        // 2. メモリ量ベースで「希望ランク」を決める
        // =========================================================
        QualityTier targetTier;

        if (isIos)
        {
            // --- iOS (メモリ効率が良いので基準値を下げる) ---
            if (systemMemory < 2500) targetTier = QualityTier.VeryLow;      // iPhone 8等 (2GB)
            else if (systemMemory < 3500) targetTier = QualityTier.Low;     // iPhone X/XR等 (3GB)
            else if (systemMemory < 4500) targetTier = QualityTier.Medium;  // iPhone 11/12/13等 (4GB)
            else if (systemMemory < 6500) targetTier = QualityTier.High;    // iPhone 13 Pro/14/15等 (6GB)
            else targetTier = QualityTier.Ultra;                            // iPad Pro/iPhone 15 Pro等 (8GB~)
        }
        else
        {
            // --- Android (メモリ消費が激しいので基準値を上げる) ---
            if (systemMemory < 3500) targetTier = QualityTier.VeryLow;
            else if (systemMemory < 4500) targetTier = QualityTier.Low;
            else if (systemMemory < 6500) targetTier = QualityTier.Medium;
            else if (systemMemory < 7500) targetTier = QualityTier.High;
            else targetTier = QualityTier.Ultra; // 8GB以上
        }

        // =========================================================
        // 3. 最終決定:希望と上限の「低い方」を採用する (安全策)
        // =========================================================
        // 例:Androidでメモリ8GB(希望Ultra) だが GPUが弱い(上限Low) の場合
        // Min(Ultra, Low) -> Low になり、カクつきを防げる。
        
        QualityTier finalTier = (QualityTier)Mathf.Min((int)targetTier, (int)maxAllowedTier);

        Debug.Log($"Spec Check | Mem: {systemMemory}MB | GPU: {graphicsTier} | Result: {finalTier}");
        
        return finalTier;
    }
}

解説:このコードの挙動シミュレーション

Mathf.Min を使って「希望」と「現実(上限)」の低い方を採用することで、以下のようにあらゆるパターンの端末を正しく捌くことができます。

端末の例 メモリ判定 (希望) GPU判定 (上限) 最終結果 判定理由
格安中華タブレット
(RAM 8GB / SoC Unisoc)
Ultra

(メモリは多い)
Low

(GPUがTier1)
Low GPUの弱さをGPU判定で見抜いてLowに落とす。
AQUOS sense6
(RAM 6GB / SoC SD690)
Medium High

(Tier2)
Medium Tier2の上限には引っかからないのでメモリ通りの判定。
iPhone 8
(RAM 2GB / SoC A11)
VeryLow High

(Tier2)
VeryLow GPUはまだ戦えるが、メモリ不足によるクラッシュを防ぐ。
Galaxy S23
(RAM 8GB / SoC SD8Gen2)
Ultra Ultra

(Tier3)
Ultra 全てが最強なのでUltra。

おまけ:解像度(DPI)も見よう

GPU性能が良くても、最近のスマホは解像度が高すぎます(Xperia 1の4Kなど)。
判定されたTierに応じて、Screen.SetResolution で解像度も調整すると完璧です。

  • VeryLow / Low: 720p相当にダウンスケール
  • Medium: 1080p相当
  • High / Ultra: ネイティブ解像度(または上限を1440pにするなど)

まとめ

スマホのスペック判定は「メモリ詐欺」と「iOS/Androidの格差」との戦いです。
ご自身のプロジェクトに合わせて微調整してみてください。

5
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?