- Home /
Is there a way to tell in Unity iOS when onDidReceiveMemoryWarning is received?
I'd like to remove textures from memory, and fall back on different shaders if I receive the onDidReceiveMemoryWarning from the iOS, but right now I do not see any documentation on how to get that message? I was wondering if anyone has done this or if there is a tool//plugin that could assist with this if Unity does not have native support for this?
There are vague mentions on the forums to check UnitySendMessage in the AppController, but I have no real idea on how to do this.
Answer by Ben-BearFish · Aug 09, 2012 at 05:47 AM
I found the answer for anyone interested.
In the AppController.mm
Look for the function:
- (void) applicationDidReceiveMemoryWarning:(UIApplication*)application
{
printf_console("WARNING -> applicationDidReceiveMemoryWarning()\n");
}
This is the function that is called when your app receives a low memory warning.
Next you must add a UnitySendMessage to your Unity code, so that you can receive the low memory warning message in your Unity code.
So, you must modify the applicationDidReceiveMemoryWarning function by writing this code:
- (void) applicationDidReceiveMemoryWarning:(UIApplication*)application
{
printf_console("WARNING -> applicationDidReceiveMemoryWarning()\n");
// This is your added call to send a message to your Unity code.
// The first parameter is the name of the class you'll be using to receive the
// low memory warning message. Mine is MemoryManager, yours can be whatever
// you name your class.
// The second parameter is the name of the method/function within your class
// that you will be using to receive the low memory warning and handle it
// appropriately however you see fit. Mine is ReceivedMemoryWarning, yours can
// be whatever you like.
// Don't forget that your function/method within your Unity C#/Javascript/etc
// code, must be a void return value with a string parameter.
// E.g.
// public void ReceivedMemoryWarning(string message)
// The third parameter can be a null string, or whatever string you want your
// message that is sent to say.
UnitySendMessage("MemoryManager", "ReceivedMemoryWarning","");
}
After you add this message call to the AppController.mm file, in your Unity code, add a new file for the class that will be receiving the message. Mine happens to be in C#, but it can be any file type. Mine is MemoyManager.cs.
Then add the code:
using UnityEngine;
using System.Collections;
public class MemoryManager : MonoBehaviour
{
//Function is called when a lowMemoryWarning is received
public void ReceivedMemoryWarning(string message)
{
Debug.Log("Memory Manager RECEIVED LOW MEMORY WARNING!");
}
}
This class now receives the message sent from the AppController.mm, and within your own function, mine is ReceivedMemoryWarning, handle how you deal with, free up memory within your game/project.
Also, it's worth mentioning if you want to modify the AppController.mm and have it update automatically in xCode every time, first create a folder in your Assets folder within the Project hierarchy window named "iOS" under the Plugins folder, so the hierarchy directory is Assets/Plugins/iOS. Then drag the AppController.mm file into that folder with your modified code, and Unity will automatically update your changes when it builds to xCode.
I hope that helps for everyone who is looking to do this, whether you're a programmer or not.
Great question and superb self-answer. This should be converted to a documentation page.
I found out more about iOS SD$$anonymous$$ to Unity communication through your answer than through the last 3-4 weeks of reading Unity's documentation and searching elsewhere online. Bravo and thank you.
Awesome answer!
There's just one issue here: Put the files in Assets/Plugins/iOS not just iOS.
http://docs.unity3d.com/Documentation/$$anonymous$$anual/PluginsForIOS.html
@ZenithCode, I updated the answer with your note. Thanks.
Answer by Renato G. · Jul 18, 2014 at 12:23 PM
Very helpful Answer. Thanks! Only one little problem with it. Since Unity 4.2 you can not just copy the AppController.mm to Assets/Plugins/iOS and Unity magically merges the stuff. Since 4.2 you can provide your own Implementation of the AppController. Here a little example for easier integration:
#import "UnityAppController.h"
@interface MyOwnAppController : UnityAppController {}
@end
@implementation MyOwnAppController
- (void)applicationDidReceiveMemoryWarning:(UIApplication*)application {
printf_console("WARNING MY OWN APP CONTROLLER -> applicationDidReceiveMemoryWarning()\n");
}
@end
IMPL_APP_CONTROLLER_SUBCLASS(MyOwnAppController)
Thats it. The magic is made by the IMPL_APP_CONTROLLER_SUBCLASS directive. Now copy this class to Assets/Plugins/iOS and you are good to go.
Happy coding.
Thanks, I was wondering why my memory controller method was not being called after updating Unity3D.
Hey, does the name have to be something specific?
I've added this thing and even added the printf_console line but it's not showing in the output of xcode.
Any idea?
Thank you! I tried to send a message in Unity to handle this situation and avoid app crash. I added in Unity a GameObject called $$anonymous$$emory$$anonymous$$anagerObj; on it I attached following code:
using UnityEngine;
public class $$anonymous$$emory$$anonymous$$anager : $$anonymous$$onoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void LackOf$$anonymous$$emory(string $$anonymous$$em$$anonymous$$sg) {
Debug.Log ("LAC$$anonymous$$ OF $$anonymous$$E$$anonymous$$ORY!!!");
}
}
and modified UnityAppController.mm this way:
#import "UnityAppController.h"
@interface iOS$$anonymous$$emory$$anonymous$$anager : UnityAppController {}
@end
@implementation iOS$$anonymous$$emory$$anonymous$$anager
- (void)applicationDidReceive$$anonymous$$emoryWarning:(UIApplication*)application {
printf_console("WARNING $$anonymous$$Y OWN APP CONTROLLER -> applicationDidReceive$$anonymous$$emoryWarning()\n");
UnityPlayer.UnitySend$$anonymous$$essage("$$anonymous$$emory$$anonymous$$anagerObj", "LackOf$$anonymous$$emory", "$$anonymous$$essage");
}
@end
I$$anonymous$$PL_APP_CONTROLLER_SUBCLASS(iOS$$anonymous$$emory$$anonymous$$anager)
Now, when memory issue occurs, in Xcode I have this message:
WARNING $$anonymous$$Y OWN APP CONTROLLER -> applicationDidReceive$$anonymous$$emoryWarning() Send$$anonymous$$essage: object $$anonymous$$emory$$anonymous$$anagerObj not found! $$anonymous$$essage from debugger: Ter$$anonymous$$ated due to memory issue
So the memory issue is caught but Send$$anonymous$$essage doesn't works, though the GameObject named $$anonymous$$emory$$anonymous$$anagerObj exists in Unity. Where I'm wrong?
Thank you!
Your gameobject named $$anonymous$$emory$$anonymous$$anagerObj must have a script attached called "$$anonymous$$emory$$anonymous$$anagerObj". So change your script from "$$anonymous$$emory$$anonymous$$anager" to "$$anonymous$$emory$$anonymous$$anagerObj " or rename your gameobject to "$$anonymous$$emory$$anonymous$$anager" and change your line: UnityPlayer.UnitySend$$anonymous$$essage("$$anonymous$$emory$$anonymous$$anagerObj", "LackOf$$anonymous$$emory", "$$anonymous$$essage"); to: UnityPlayer.UnitySend$$anonymous$$essage("$$anonymous$$emory$$anonymous$$anager", "LackOf$$anonymous$$emory", "$$anonymous$$essage");
Thank you Ben! I followed your instructions changing the script name from "$$anonymous$$emory$$anonymous$$anager" to "$$anonymous$$emory$$anonymous$$anagerObj", as you can see in image. Then I modified UnityAppController.mm in Xcode this way:
- (void)applicationDidReceive$$anonymous$$emoryWarning:(UIApplication*)application
{
::printf("WARNING -> applicationDidReceive$$anonymous$$emoryWarning()\n");
UnitySend$$anonymous$$essage("$$anonymous$$emory$$anonymous$$anagerObj", "LackOf$$anonymous$$emory", "$$anonymous$$essage");
UnityLow$$anonymous$$emory();
}
But I still have:
WARNING -> applicationDidReceive$$anonymous$$emoryWarning() Send$$anonymous$$essage: object $$anonymous$$emory$$anonymous$$anagerObj not found! $$anonymous$$essage from debugger: Ter$$anonymous$$ated due to memory issue
What do you think?
Thank you!
[1]: /storage/temp/94379-memorymanagerobj.png
void LackOf$$anonymous$$emory isn't public. ie. the function should be:
public void LackOf$$anonymous$$emory(string $$anonymous$$em$$anonymous$$sg) { Debug.Log ("LAC$$anonymous$$ OF $$anonymous$$E$$anonymous$$ORY!!!"); }
Answer by Kubic75 · Sep 01, 2017 at 04:43 PM
This is currently the correct and most up-to-date answer. I would use this answer from now on. The Best Answer is for legacy versions of Unity.