You can profile your memory usage using Instruments through XCode. Simply select Product > Profile from the menu bar, which will compile your app, put it on the device, and automatically open up Instruments (using XCode4, might be the same in XCode3). If you then select “Activity Monitor,” you’ll get a lot of data on the amount of memory you are using. Depending on your testing device, the acceptable amount of RAM varies.
iPhone3 (128MB total RAM): less than 40MB
iPad1 or iPhone3GS (256MB total RAM): less than 80MB
iPhone4, iPhone4S, iPad2 (512MB total RAM): less than 160MB
Another thing you might want to do is watch your XCode log and see if you are receiving memory warnings. Memory warnings are a pretty good indicator that you are using too much memory and the OS might shut you down.
Then, I’ve found the following code pretty useful to see everything that is loaded in memory at a given time. It will slow down your build a little bit because it uses UnityGUI, so use it for debugging only, not in production builds:
public class DetectLeaks : MonoBehaviour
{
private static DetectLeaks instance;
void Awake()
{
if(instance == null)
{
instance = this;
}
else
{
Destroy(this);
}
}
void Start()
{
DontDestroyOnLoad(gameObject);
}
void OnGUI()
{
if(GUILayout.Button("Unload Unused Assets"))
{
Resources.UnloadUnusedAssets();
}
if(GUILayout.Button("Mono Garbage Collect"))
{
System.GC.Collect();
}
if(GUILayout.Button("List Loaded Textures"))
{
ListLoadedTextures();
}
if(GUILayout.Button("List Loaded Sounds"))
{
ListLoadedAudio();
}
if(GUILayout.Button("List Loaded GameObjects"))
{
ListLoadedGameObjects();
}
}
private void ListLoadedTextures()
{
Object[] textures = Resources.FindObjectsOfTypeAll(typeof(Texture));
string list = string.Empty;
for(int i = 0; i < textures.Length; i++)
{
if(textures*.name == string.Empty)*
_ list += (i.ToString() + ". " + textures*.name + "
");*_
* if(i == 500)*
* {*
* Debug.Log(list);*
* list = string.Empty;*
* }*
* }*
* Debug.Log(list);*
* }*
* private void ListLoadedAudio()*
* {*
* Object[] sounds = Resources.FindObjectsOfTypeAll(typeof(AudioClip));*
* string list = string.Empty;*
* for(int i = 0; i < sounds.Length; i++)*
* { *
_ if(sounds*.name == string.Empty)
{
continue;
}
list += (i.ToString() + ". " + sounds.name + "
");
}*_
* Debug.Log(list);*
* }*
* private void ListLoadedGameObjects()*
* {*
* Object[] gos = Resources.FindObjectsOfTypeAll(typeof(GameObject));*
* string list = string.Empty;*
* for(int i = 0; i < gos.Length; i++)*
* {*
_ if(gos*.name == string.Empty)
{
continue;
}
list += (i.ToString() + ". " + gos.name + "
");
}*_
* Debug.Log(list);*
* }*
}
Finally, Resources.UnloadUnusedAssets() will only work if the asset is truly unused - that is, if there is no remaining script reference to the asset. If any Monobehavior is holding a reference, or if you have a link to a prefab that contains the asset, it will probably not be unloaded as a result of calling this. It is tricky to manage sometimes.
Hope this helps, and good luck!