Oscar
Oscar

Reputation: 96

stop a function from being called every frame c#

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

Answers (3)

Lece
Lece

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

Doh09
Doh09

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.

Unity lifecycle

More information about Unity's Lifecycle can be found at: https://docs.unity3d.com/Manual/ExecutionOrder.html

Upvotes: 0

McAden
McAden

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

Related Questions