LoginSignup
29
26

More than 5 years have passed since last update.

Unity+iOSでMemoryWarning発生時にSystem.GCとかResources.Unloadとかさせる

Last updated at Posted at 2015-01-31

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世界へメッセージを送る

上で作っておいたMyAppControllerapplicationDidReceiveMemoryWarning関数から、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自体は解決してないのですけどね・・・

29
26
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
29
26