Unityで取得できるシステム情報

※2016/11/17 必要に迫られて描画APIの表示を追加しました。

![InGameProfiler.png](https://qiita-image-store.s3.amazonaws.com/0/141731/d876dc16-8e25-0d25-fbb5-0ad2f22c393f.png)

Unityは使用メモリを取得するAPIの戻り値がそれほど正確でないという話もあるんですが、正確なものは最終的に最適化をする人にProfilerで見てもらうとして、目安として画面上に表示しておくのはそれなりに便利じゃないかなーと思います。ということで、開発に必要そうなシステム情報を取得するC#スクリプトを書いてみました。

MonoBehaviour.OnGUI()は重いという話なのでuGUIで実装しました。なので単体では動作せず、Canvas上にTextコンポーネントを持つGameObjectを置いて、このInGameProfiler.csをAddして使ってください。

取得できるのは、
1. OS名
2. CPUの種類と周波数とコア数
3. GPUの種類と周波数とメモリサイズと描画API
4. 画面解像度とリフレッシュレート
5. オーディオ再生周波数とチャンネル数とバッファ
6. デバイスのメモリ量と使用メモリ量とGCカウント
7. 実際のフレームレート(推定)
です。

他にも出したいものはあるんですが、Profiler Windowでしか見れないものが多いんですよねー。実機単体で見たい場合も多いと思うんですけども…。

```InGameProfiler.cs
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class InGameProfiler : UIBehaviour
{
    protected override void Start()
    {
        base.Start();
#if DEVELOPMENT_BUILD || UNITY_EDITOR
        m_text = gameObject.GetComponent<Text>();

        m_os_info = string.Format("OS: {0}", SystemInfo.operatingSystem);
        m_cpu_info = string.Format("CPU: {0} / {1}cores", SystemInfo.processorType, SystemInfo.processorCount);
        m_gpu_info = string.Format("GPU: {0} / {1}MB API: {2}", SystemInfo.graphicsDeviceName, SystemInfo.graphicsMemorySize, SystemInfo.graphicsDeviceType);

        AudioSettings.OnAudioConfigurationChanged += OnAudioConfigurationChanged;
        OnAudioConfigurationChanged(true);
        OnRectTransformDimensionsChange();

        m_start_time = Time.time;
#else
        gameObject.SetActive(false);
#endif
    }

#if DEVELOPMENT_BUILD || UNITY_EDITOR
    void Update()
    {
        ++m_frame_counts;
        float currentTime = Time.time;
        float diffTime = currentTime - m_start_time;
        if (diffTime >= 1.0f)
        {
            m_fps = m_frame_counts / diffTime;
            m_start_time = currentTime;
            m_frame_counts = 0;
            gameObject.transform.SetAsLastSibling();    // 毎フレームは重いのでここで最前面に持って来る
        }

        const uint mega = 1024 * 1024;
        string memory = string.Format("Memory: {0:####.0} / {1}.0MB GCCount: {2}", Profiler.usedHeapSize / (float)mega, SystemInfo.systemMemorySize, System.GC.CollectionCount(0));
        string performance = string.Format("Performance: {0:#0.#}fps", m_fps);
        if (m_text != null)
        {
            m_text.text = m_os_info + System.Environment.NewLine +
                m_cpu_info + System.Environment.NewLine +
                m_gpu_info + System.Environment.NewLine +
                m_resolution_info + System.Environment.NewLine +
                m_audio_info + System.Environment.NewLine +
                memory + System.Environment.NewLine +
                performance;
        }
    }

    void OnAudioConfigurationChanged(bool deviceWasChanged)
    {
        int bufferLength, numBuffers;
        AudioSettings.GetDSPBufferSize(out bufferLength, out numBuffers);
        AudioConfiguration config = AudioSettings.GetConfiguration();
        m_audio_info = string.Format("Audio: {0:#,#}Hz {1} {2}samples {3}buffers", config.sampleRate, config.speakerMode.ToString(), config.dspBufferSize, numBuffers);
    }

    protected override void OnRectTransformDimensionsChange()
    {
        Resolution reso = Screen.currentResolution;
        m_resolution_info = string.Format("Resolution: {0} x {1} RefreshRate: {2}Hz", reso.width, reso.height, reso.refreshRate);
    }

    private Text m_text;
    private string m_os_info;
    private string m_cpu_info;
    private string m_gpu_info;
    private string m_resolution_info;
    private string m_audio_info;
    private int m_frame_counts;
    private float m_start_time;
    private float m_fps;
#endif
}
```

ちなみに実装のキモは、画面が回転したタイミングで画面解像度情報を更新するために、MonoBehaviourではなくUIBehaviourの派生クラスにして、OnRectTransformDimensionsChangeをoverrideするところ。