I agree with YoungDeveloper that you are doing a lot of unnecessary calculations every frame. Almost all the variables in OnGUI can be stored in variables at Start() instead of calculated every OnGUI() call. Normally you can get away with doing a bit of that although it’s bad practice. In your case I would convert pretty much everything to preset variables if you really are lagging that bad.
Also I think an even bigger problem for you is that you are using those for() loops in your OnGUI(). I think that’s a REALLY bad idea and should be removed immediately from your code if at all possible. The reason why you’re getting such horrendous lag is that OnGUI() may be having a hard time keeping up with those For() loops.
I don’t know the details of onGUI() well enough but it’s quite possible it does not wait to complete one cycle before it starts the next one so you could have multiple identical for loops executing simultaneously? I don’t know if that’s even possible but if the game gets laggier the longer you have the menu open I think that’s the cause.
So I think the solution is to declare as many of those variables as possible into your Start() function. And get rid of all those For() loops. Your GUI should already know what to do with pre-existing variables whenever possible, keep the logic in there to a minimum.
I just counted the objects in one of my scenes which has the most enemies and there is over 60 objects in the scene all with unique and active OnGUI() included in their scripts. This also includes the biggest OnGUI script in my game that controls the majority of button logic, as well as the main menu which has options, inventory, player stats, displays all the GUI stuff in inventory and on a picture of the player and updates the stat numbers like Strength, Intelligence for each piece etc. This script is nearly 5000 lines of code long (but uses if statements to skip huge sections that are irrelevant to the current display). And I don’t lag at all from OnGUI() on either of my phones.
So my point is if you just have one script that is causing so many problems something is SERIOUSLY wrong I think it’s the for() loops. And doing that many calculations is makign the For Loops way worst. all those calculations every OnGUI().
Here’s an example of how I set up some of the level selection stuff that I think is a lot more performance friendly. I tried to just grab some code snippets directly from my project not really bothering to format it much and include every detail:
Vector3 matrixVector;
float native_width = 1280;
float native_height = 720;
float rx;
float ry;
void Start()
{
float rx = Screen.width/ native_width;
float ry = Screen.height / native_height;
//set matrix to format all GUI easy
matrixVector = new Vector3 (rx, ry, 1);
//get certain playerprefs to avoid having to retrieve them excessively
levelsUnlockedInt = PlayerPrefs.GetInt ("Levels Unlocked");
if (PlayerPrefs.GetInt ("World Select Button", 1) == 1)
{
worldSelectInt = 1;
}
audio.Play();
//etc more playerPrefs or bools variables whatever you need to reduce amount of stuff in OnGUI()
}
Void OnGUI()
{
//THIS MATRIX IS MOST IMPORTANT PART!!!
//ALLOWS YOU TO EASILY SET RESOLUTION TO ANY SCREEN SIZE
// CAN BE DONE ACCURATELY THROUGHOUT THE ENTIRE PROJECT IF SET UP RIGHT
GUI.matrix = Matrix4x4.TRS (new Vector3(0, 0, 0), Quaternion.identity, matrixVector);
//FUNCTION TO DISPLAY LOADING SCREEN AFTER THIS BOOL IS SET WHEN THEY HIT LEVEL
if (GlobalDataScript.loadingScreenImageBool == true)
{
GUI.DrawTexture (new Rect(0, 0, 1280, 720), loadingScreenTexture);
//ONCE LOADING SCREEN SET LOAD LEVEL
StartLoadingScreenReadyFunction();
return;
}
//code before getting to level select screen
else if (levelSelectBool == true)
{
//BACKGROUND TEXTURE
GUI.DrawTexture (new Rect(0, 0, native_width, native_height), levelSelectBackgroundTexture);
//}
//notice how all buttons can be specific coordinates thanks to Matrix!
//Even better if you set all those positions and sizes for buttons as Vector2 on Start()
//exit the level Select Texture
if (GUI.Button (new Rect (980, 620, 300, 100), returnTexture, startGameStyle))
{
SoundPlayerScript otherObjectsScriptSoundPlayer = soundObject.GetComponent<SoundPlayerScript>();
otherObjectsScriptSoundPlayer.button1SoundFunction();
levelSelectBool = false;
//GlobalDataScript.loadingScreenImageBool = true;
//loadingLevelInt = 1;
}
//example of optional details about player progress
GUI.Label (new Rect (720, 80, 100, 100), "Tier 1 Armor Set Pieces Found: " + GlobalDataScript.tierOneArmorPiecesFound
+ "/5", levelMysteryStyle);
//which world is selected
//WORLD 1 button color and logic control
if (worldSelectInt == 1)
{
if (GUI.Button (new Rect (540, 0, 240, 80), worldOneTextureSelected, startGameStyle))
{
SoundPlayerScript otherObjectsScriptSoundPlayer = soundObject.GetComponent<SoundPlayerScript>();
otherObjectsScriptSoundPlayer.button1SoundFunction();
PlayerPrefs.SetInt ("World Select Button", 1);
worldSelectInt = 1;
}
}
else if (GUI.Button (new Rect (540, 0, 240, 80), worldOneTexture, startGameStyle))
{
SoundPlayerScript otherObjectsScriptSoundPlayer = soundObject.GetComponent<SoundPlayerScript>();
otherObjectsScriptSoundPlayer.button1SoundFunction();
PlayerPrefs.SetInt ("World Select Button", 1);
worldSelectInt = 1;
}
//WORLD 2 button color and logic control
if ((levelsUnlockedInt >= 7) && (worldSelectInt == 2))
{
if (GUI.Button (new Rect (780, 0, 240, 80), worldTwoTextureSelected, startGameStyle))
{
SoundPlayerScript otherObjectsScriptSoundPlayer = soundObject.GetComponent<SoundPlayerScript>();
otherObjectsScriptSoundPlayer.button1SoundFunction();
PlayerPrefs.SetInt ("World Select Button", 2);
worldSelectInt = 2;
}
}
else if (levelsUnlockedInt >= 7)
{
if (GUI.Button (new Rect (780, 0, 240, 80), worldTwoTexture, startGameStyle))
{
SoundPlayerScript otherObjectsScriptSoundPlayer = soundObject.GetComponent<SoundPlayerScript>();
otherObjectsScriptSoundPlayer.button1SoundFunction();
PlayerPrefs.SetInt ("World Select Button", 2);
worldSelectInt = 2;
}
}
//etc more worlds
}
//WORLD 1 level buttons
if (worldSelectInt == 1)
{
if (GUI.Button (new Rect (0, 170, 300, 100), levelOneTexture, startGameStyle))
{
GlobalDataScript.playerAtStoreInt = 0;
GlobalDataScript.currentLevelInt = 1;
GlobalDataScript.loadingScreenImageBool = true;
loadingLevelInt = 4;
SoundPlayerScript otherObjectsScriptSoundPlayer = soundObject.GetComponent<SoundPlayerScript>();
otherObjectsScriptSoundPlayer.button2SoundFunction();
}
if (levelsUnlockedInt >= 1)
{
if (GUI.Button (new Rect (0, 320, 300, 100), levelTwoTexture, startGameStyle))
{
SoundPlayerScript otherObjectsScriptSoundPlayer = soundObject.GetComponent<SoundPlayerScript>();
otherObjectsScriptSoundPlayer.button2SoundFunction();
GlobalDataScript.playerAtStoreInt = 0;
GlobalDataScript.currentLevelInt = 2;
GlobalDataScript.loadingScreenImageBool = true;
loadingLevelInt = 5;
}
}
if (levelsUnlockedInt >= 2)
{
if (GUI.Button (new Rect (0, 470, 300, 100), levelThreeTexture, startGameStyle))
{
SoundPlayerScript otherObjectsScriptSoundPlayer = soundObject.GetComponent<SoundPlayerScript>();
otherObjectsScriptSoundPlayer.button2SoundFunction();
GlobalDataScript.playerAtStoreInt = 0;
GlobalDataScript.currentLevelInt = 3;
GlobalDataScript.loadingScreenImageBool = true;
loadingLevelInt = 6;
}
}
//etc buttons for all other levels on that world..
}
//any other displays that should be visible on any world
}
//loads the level after the loading screen is set in OnGUI() and this function is called
void StartLoadingScreenReadyFunction()
{
Application.LoadLevel(loadingLevelInt);
}