Reputation: 96
I am trying to create a list of buttons using information collected from www forms in my program. The problem I am having is that when I create the buttons, it infinitely creates them, and thusly unity crashes. I have two theories as to why this is happening, the first being that the function is being called each frame and is therefore creating too many buttons and the second is that for some reason when I check the length of a multidimensional array it has a length of 33 when it should only have a length of 3 (it should have 3 arrays of arrays). The whole script is below.
using Boo.Lang;
using System.Collections;
using SCG = System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System;
public class MeetingRequestViewer : MonoBehaviour
{
//This script contains the code on how to display information about the students to the staff
//it displays each student in a different row
private Rect windowRect = new Rect(0, 0, Screen.width, Screen.height);
public Vector2 scrollPosition = Vector2.zero;
private int BSpace;
public string[,] SortedStudentArray;
private int j;
private string[][] MeetRequests;
private string[] temp;
private SCG.List<string> H_Priority = new SCG.List<string>();
private SCG.List<string> M_Priority = new SCG.List<string>();
private SCG.List<string> L_Priority = new SCG.List<string>();
private SCG.List<string> FullList = new SCG.List<string>();
private SCG.List<string> UAList;
private SCG.List<object> StudentButtonList = new SCG.List<object>();
private string[] Holding = new string[5];
private string[] SearchTerms;
public int ButtonSpacing = 10;
public int ButtonWidth = 80;
public int ButtonHeight = 30;
public void OnGUI()
{
//create a window
GUI.Window(0, windowRect, WindowFunction, "Meeting Request Viewer");
}
public void WindowFunction(int windowID)
{
//Fetches all user Data
string[][] userArray = GetComponent<Userdata>().CallDetail();
string[][] StudentArray = GetComponent<Userdata>().UserSorting(userArray);
//Calls the SortStudentArray method
string[,] SortedStudentArray = SortStudentList();
//Creates a box with a scrolling bar to taverse the y axis
scrollPosition = GUI.BeginScrollView(new Rect(Screen.width / 6, Screen.height / 6, 350, 250), scrollPosition, new Rect(0, 0, 300, 40 * SortedStudentArray.Length));
//for each row in the sorted student array
for (int x = 0; x < SortedStudentArray.Length - 1; x++)
{
//This keeps the gap between each button consistent
var y = ButtonSpacing + ButtonHeight;
//Regular Meeting Request
if (SortedStudentArray[x, 7] == "1")
{
//Urgent Meeting Request
if (SortedStudentArray[x, 8] == "1")
{
Debug.Log("Even Here");
//Create Button coloured red
GUI.backgroundColor = Color.red;
}
//Regular Meeting Request
else
{
//Create Button coloured yellow
GUI.backgroundColor = Color.yellow;
}
}
//No Meeting Request
else
{
//Create Button coloured green
GUI.backgroundColor = Color.green;
}
GUI.Button(new Rect(ButtonSpacing, ButtonSpacing + x * y, ButtonWidth, ButtonHeight), SortedStudentArray[x, 6]);
}
GUI.EndScrollView();
ButtonsCreated = true;
}
private string[,] SortStudentList()
{
//This method is used to fetch the meeting request data, split it into a jagged array and then again so that each
//row is a new user and each item in the row is a different peice of information relating to the user
//The Jagged array is then sorted using the bubble sort algorithm so that the students that require urgent meetings
//appear at the topo of the request table
//call website with the data store
WWW MeetReqData = new WWW("http://localhost/Wellbeing/meetingrequest.php");
//until WWW is finished do nothing
while (MeetReqData.isDone == false)
{
}
//convert the returned value into a string
string MeetReqString = MeetReqData.text;
//split the text into a string list
string[] mrq = MeetReqString.Split(';');
//convert the string list into a jagged array
MeetRequests = new string[mrq.Length][];
int i = 0;
//for each item in the list
foreach (string s in mrq)
{
//split it into its individual peice of information
string[] g = s.Split('|');
//store the information about a user on a new line
MeetRequests[i] = g;
++i;
}
for (int n = 0; n < MeetRequests.Length - 1; n++)
{
if (MeetRequests[n][1] == "1" && MeetRequests[n][2] == "1")
{
H_Priority.Add(MeetRequests[n][0]);
}
else if (MeetRequests[n][1] == "1" && MeetRequests[n][2] == "0")
{
M_Priority.Add(MeetRequests[n][0]);
}
else
{
L_Priority.Add(MeetRequests[n][0]);
}
}
//Combines all lists into a larger list of priorities
FullList.AddRange(H_Priority);
FullList.AddRange(M_Priority);
FullList.AddRange(L_Priority);
//convertFullList into an array for easier mainpulation and comparisons
string[][] feelingsArray = GetComponent<Userdata>().CallFeelings();
//FullList only contains 3 values
Debug.Log(FullList.Count);
//Info array about each user
string[,] SortedStudentArray = new string[FullList.Count, 11];
//SortedStudentArray contains 33 rows
Debug.Log("This thing Here");
Debug.Log(SortedStudentArray.Length);
//Line Counter
int SSAPos = 0;
// For every element in FullList
foreach (var item in FullList)
{
Debug.Log(FullList.Count);
//For each user in userArray
for (int y = 0; y < Userdata.userArray.Length; y++)
{
if (Userdata.userArray[y][0] == item)
{
for (int n = 0; n < Userdata.userArray; n++)
SortedStudentArray[SSAPos, n] = Userdata.userArray[y][n];
break;
}
}
Debug.Log(SortedStudentArray.Length);
//For each user in userArray
for (int y = 0; y < MeetRequests.Length; y++)
{
if (MeetRequests[y][0] == item)
{
SortedStudentArray[SSAPos, 7] = MeetRequests[y][1];
SortedStudentArray[SSAPos, 8] = MeetRequests[y][2];
break;
}
}
Debug.Log(SortedStudentArray.Length);
SSAPos += 1;
}
return SortedStudentArray;
}
// Update is called once per frame
void Update ()
{
//if (GUI.Button(new Rect(Screen.width / 4, Screen.height / 7, Screen.width / 2, Screen.height / 8), "Log Out"))
//{
// Debug.Log("Logged Out");
// SceneManager.LoadScene("Login");
//}
}
I did try to use a while loop around the section of code however it made no difference to the creation of buttons, they were still created more times than were needed
Upvotes: 0
Views: 751
Reputation: 2377
FullList
is continually being populated which will eventually lead to a crash.
Call SortStudentList
in Awake
, such as;
string[,] SortedStudentArray;
void Awake ()
{
//Calls the SortStudentArray method
SortedStudentArray = SortStudentList();
}
Then;
public void WindowFunction(int windowID)
{
// Prevent further execution until SortedStudentArray is ready
if (SortedStudentArray == null) return;
...
}
Upvotes: 2
Reputation: 2385
https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnGUI.html
OnGUI is called for rendering and handling GUI events.
This means that your OnGUI implementation might be called several times per frame (one call per event). For more information on GUI events see the Event reference. If the MonoBehaviour's enabled property is set to false, OnGUI() will not be called.
You should probably use another way to call your method, or use a boolean value to check whether or not it has already been called.
Please refer to the image below to better understand the Unity lifecycle methods.
More information about Unity's Lifecycle can be found at: https://docs.unity3d.com/Manual/ExecutionOrder.html
Upvotes: 0
Reputation: 13972
From the documentation:
OnGUI is called for rendering and handling GUI events.
This means that your OnGUI implementation might be called several times per frame (one call per event). For more information on GUI events see the Event reference. If the MonoBehaviour's enabled property is set to false, OnGUI() will not be called.
You need to reevaluate how you're doing your GUI. As mentioned in their GUI scripting guide you should probably use their UI system.
You especially don't want to be making one or more WWW
calls per frame, or doing a bunch of sorting every frame.
Upvotes: 1