Unity でアプリケーションを作成するとき、アプリケーション自体が消費しているメモリー量は常に意識したほうがよいと思います。
詳しく調べるときは「Unity Profiler」を使って調べると思いますが、常に意識するには大仰なものかもしれません。
そんなわけなので、最低限のメモリー使用量を把握するポイントをまとめた記事になります。具体的には、下記のようなものを作りました。
対象は、Unity Editor (Windows), Android です。その他のプラットフォーム対応は参考を確認ください。
監視するメモリー量のポイント
アプリケーションが消費しているメモリー量を監視するポイントは図のように3段階に分かれています。
1と2の部分を Unity アプリケーション開発者がどうこうすることは難しいので、基本的には「3」の使用量を抑える(自分で決めた目標値以内に収める)ことで、アプリケーション全体のメモリー使用量を良い具合にする=アプリ動作を快適にする、ということだと思います。
話を難しくしているのは、「1」の取得方法が、端末ごとに異なるためややこしいのだと思います。
1「アプリケーション全体」の消費メモリーの取得方法
Unity Editor (Windows)
DLL を作成してメモリー使用量を取得することになります。詳細は「Windowsアプリのメモリ使用量を取得する」に詳しいです。
私が作成したものは「Sample - UnityNativeUtil」に公開しています。
[DllImport("UnityNativeUtil")] public extern static long GetWorkingSet(); [DllImport("UnityNativeUtil")] public extern static long GetWorkingSetAndSwap(); entireAppUsedMemory = GetWorkingSet();
下記のフォルダに「*.dll」を追加します。
Assets\Plugins
Android
aar モジュールを作成して、メモリー量を取得することになります。詳細は「標準Profilerだけに頼らないUnityのプロファイリングに挑んでみる」に詳しいです。
プラグインを作成する方法は「Unity向けAndroidネイティブプラグインの作り方」などを参考にしてみてください。
私が作成したコードは以下のとおりです。
package com.sh1.usedmemoryutil; import com.unity3d.player.UnityPlayer; import android.os.Debug; import android.os.Process; import android.app.ActivityManager; import android.content.Context; public class NativeMemoryWatcher { /** * 現在使用しているメモリー量を取得します。 * @return 現在使用しているメモリー量(byte 単位) */ public static long GetUsedMemory() { final Context context = UnityPlayer.currentActivity.getApplication().getApplicationContext(); final ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); final Debug.MemoryInfo[] memoryInfo = activityManager.getProcessMemoryInfo(new int[]{ Process.myPid() }); long usedMemory = 0; for (Debug.MemoryInfo info : memoryInfo) { usedMemory += info.getTotalPss() * 1024; // KB 単位を byte 単位に変換 } return usedMemory; } }
using System; using System.Collections; using System.Collections.Generic; using System.Runtime.InteropServices; using UnityEngine; using UnityEngine.Profiling; using UnityEngine.UI; public class MemoryAmountInfo : MonoBehaviour { private AndroidJavaClass _NativeClass = null; private const string PACKAGE_NAME = "com.sh1.usedmemoryutil"; private const string CLASS_NAME = "NativeMemoryWatcher"; private const string METHOD_NAME = "GetUsedMemory"; [DllImport("UnityNativeUtil")] public extern static long GetWorkingSet(); [DllImport("UnityNativeUtil")] public extern static long GetWorkingSetAndSwap(); // Start is called before the first frame update void Start() { _NativeClass = new AndroidJavaClass($"{PACKAGE_NAME}.{CLASS_NAME}"); } void OnDestroy() { _NativeClass?.Dispose(); _NativeClass = null; } // Update is called once per frame void Update() { // n秒ごとに更新するなどの処理を追加してください string text = ""; float entireAppUsedMemory = -1; try { #if UNITY_EDITOR entireAppUsedMemory = ToMB(GetWorkingSet()); #elif UNITY_ANDROID entireAppUsedMemory = ToMB(_NativeClass.CallStatic<long>(METHOD_NAME)); #endif var usedMB = ToMB(Profiler.GetTotalAllocatedMemoryLong()); var poolMB = ToMB(Profiler.GetTotalReservedMemoryLong()); var usedPercent = usedMB / poolMB * 100; if (entireAppUsedMemory > 0) { text = $"entire: {entireAppUsedMemory:0.00} MB" + "\n"; } text += $"pool : {usedMB:0.00} / {poolMB:0.00} MB ({usedPercent:0.00} %)"; } catch (Exception e) { Debug.Log(e.Message); } Debug.Log(text); } private float ToKB(long memory) => memory / 1024F; private float ToMB(long memory) => memory / 1024F / 1024F; }
下記のフォルダに「*.aar」を追加します。
Assets\Plugins\Android
2、3「Unity が管理する」メモリー使用量の取得
Unity が管理するパラメーターは、Unity の提供するメソッドから取得することができます。
- プールとして用意してくれているメモリー使用量
Profiler.GetTotalReservedMemoryLong() - 現在使用しているメモリー使用量
Profiler.GetTotalAllocatedMemoryLong()
取得した値は、byte 単位なので感覚的に掴めないため、MB くらいに変換すると見やすくなります。
private float ToKB(long memory) => memory / 1024F; private float ToMB(long memory) => memory / 1024F / 1024F;
消費メモリー量をどの程度に抑えるか?
Android 端末のメモリー使用量は、開発者モードにすることで詳細を確認することができます。このあたりは、他のアプリケーションのメモリー使用量を把握して、どの程度がよいのか目安を設けるのがよいと思います。
Simple System Monitor というアプリを入れることでも計測することができると思います。
2012年ごろのアプリだと 100MB に抑えるといった、「Unityとスマートフォンアプリの最適化」の33ページの情報も見つかりました。しかし、現在だと Unity のアプリの全体消費量を 100MB に収めるのはかなり困難だと思います。
メモリー消費量という言葉が指すのは、全体なのかプールのか留意したほうがよいと思います。
使用メモリー例
スマートフォンに入っていたゲームを3つほど動かした結果を記録しておきます。どれも、1~2戦やっただけなので動作時間は数分です。
例1(ダンジョンメーカー)
例2(お城プロジェクト:RE)
例3(アイギス)
参考
- KLabGames - 標準Profilerだけに頼らないUnityのプロファイリングに挑んでみる
- ギャップロ - Unity向けAndroidネイティブプラグインの作り方
- てんぷらブログ - FPSMemoryFriends – UnityでAndroid/iOSのFPSとメモリ使用量を取得する
- Cooooding!! - Unityで使えるメモリ量を取得する方法まとめ
- Karasuのアプリ奮闘記 - 使用メモリ量を常に視覚化しよう!
- 【CEDEC2018】一歩先のUnityでのパフォーマンス/メモリ計測、デバッグ術
- Qiita - やはりUNITYでAndroidプラグインを作るにはAndroidJavaClassが便利だ
- 作者:一條 貴彰
- 発売日: 2019/08/27
- メディア: 単行本