Objective-CでMemoryWarningを受け取れるようにする
ネイティブの処理を書けるようにする
まず、Assets/Plugins/iOS/
以下に、MyAppController.mm
ファイルを作成します。
MyAppController
にはUnityAppController
を継承させます。
IMPL_APP_CONTROLLER_SUBCLASS(MyAppController)
することで、UnityAppController
の代わりにMyAppController
が使われるようになります。
# import "UnityAppController.h"
@interface MyAppController : UnityAppController
@end
@implementation MyAppController
@end
IMPL_APP_CONTROLLER_SUBCLASS(MyAppController)
あとは、このMyAppControllerを改造すれば、何でも処理をいれられます。
applicationDidReceiveMemoryWarningを実装する
# import "UnityAppController.h"
@interface MyAppController : UnityAppController
@end
@implementation MyAppController
- (void) applicationDidReceiveMemoryWarning:(UIApplication*)application
{
[super applicationDidReceiveMemoryWarning:application];
printf_console("メモリやばいよ\n");
}
@end
IMPL_APP_CONTROLLER_SUBCLASS(MyAppController)
こんな感じです。
シミュレータでHardware/Simulate Memory Warning
を実行してみて"メモリやばいよ"が見えれば成功です。
Unity世界でMemoryWarningを受け取る窓口を作る
MonoBehaviour
を継承して、MemoryWarningを受け取るコンポーネントを作ります。
using UnityEngine;
public class MemoryWarningReciever : MonoBehaviour
{
public void DidReceiveMemoryWarning (string message)
{
Debug.Log ("メモリやばいってよ:" + message);
Debug.Log ("GCするよ");
System.GC.Collect ();
Debug.Log ("使ってなさそうなアセットを開放するよ");
Resources.UnloadUnusedAssets ();
}
}
これをシーン中のゲームオブジェクトにアタッチしておきます。
わかりやすく、ゲームオブジェクトの名前もMemoryWarningReciever
にしておきましょう。
ネイティブ世界からUnity世界へメッセージを送る
上で作っておいたMyAppController
のapplicationDidReceiveMemoryWarning
関数から、MemoryWarningReciever
をアタッチされたゲームオブジェクトにメッセージを送るためにUnitySendMessage
関数を使います。
- (void) applicationDidReceiveMemoryWarning:(UIApplication*)application
{
[super applicationDidReceiveMemoryWarning:application];
printf_console("メモリやばいよ\n");
UnitySendMessage("MemoryWarningReciever", "DidReceiveMemoryWarning","");
}
UnitySendMessage
関数の第一引数はオブジェクト名、第二引数が関数名です。
実行ログ
2015-02-01 04:52:23.109 ProductName[29257:223014] Received memory warning.
WARNING -> applicationDidReceiveMemoryWarning()
メモリやばいよ
メモリやばいってよ:
UnityEngine.Debug:Internal_Log(Int32, String, Object)
UnityEngine.Debug:Log(Object)
MemoryWarningReciever:DidReceiveMemoryWarning(String) (at /Users/hoge/moge/Assets/MemoryWarningReciever.cs:9)
(Filename: /Users/hoge/moge/Assets/MemoryWarningReciever.cs Line: 9)
GCするよ
UnityEngine.Debug:Internal_Log(Int32, String, Object)
UnityEngine.Debug:Log(Object)
MemoryWarningReciever:DidReceiveMemoryWarning(String) (at /Users/hoge/moge/Assets/MemoryWarningReciever.cs:10)
(Filename: /Users/hoge/moge/Assets/MemoryWarningReciever.cs Line: 10)
使ってなさそうなアセットを開放するよ
UnityEngine.Debug:Internal_Log(Int32, String, Object)
UnityEngine.Debug:Log(Object)
MemoryWarningReciever:DidReceiveMemoryWarning(String) (at /Users/hoge/moge/Assets/MemoryWarningReciever.cs:12)
(Filename: /Users/hoge/moge/Assets/MemoryWarningReciever.cs Line: 12)
System memory in use before: 1.0 MB.
Unloading 2 Unused Serialized files (Serialized files now loaded: 0 / Dirty serialized files: 0)
System memory in use after: 1.0 MB.
Unloading 1 unused Assets to reduce memory usage. Loaded Objects now: 102.
Total: 0.632223 ms (FindLiveObjects: 0.063613 ms CreateObjectMapping: 0.013408 ms MarkObjects: 0.159459 ms DeleteObjects: 0.019284 ms)
ただし、System.GCしても、リソース開放しても、アセットバンドル開放しても、MonoがOSから確保したメモリ領域そのものが開放されるわけじゃないので、MemoryWarning自体は解決してないのですけどね・・・