Custom Inspector Button Crashing,Custom Inspector Script Crashing
So I am working on writing a simple random generation script that creates a random pattern of platforms for an arcade game I am working on. I also wrote a custom editor that contains a button I can press to test the random gen script without having to run the entire game for every test. The problem is every 3rd time I try to click the random gen button It causes unity to freeze completely. The script doesn't seem to be the problem since whenever I run the entire game it works perfectly. Any ideas as to what the cause might be? Thanks.
Random Gen Script
using UnityEngine;
using UnityEditor;
public class GameGenerator : MonoBehaviour {
[Header("Position Checking Vars")]
public float xCheck = 0.25f;
public float yCheck = -2.25f;
[Header("Board Boundary Vars")]
public float leftBoader = -2.25f;
public float rightBoarder = 0.75f;
public float bottomeBoarder = -2.25f;
public float topBoader = 2.25f;
public float PositionIncrement = 0.75f;
[Header("Start Position Trackers")]
public bool[] startPosTrackers;
[Header("Instantiation Prefabs")]
public GameObject platform;
[Header("Generator Customization Vars")]
public int MaxHorizontalPlatforms = 5;
public int NumberOfRows = 7;
[Range(1f, 5f)]
public int NumberOfTrackers = 3;
private void Start()
{
GenerateStartBoard();
}
private Vector3 FindStartPosition()
{
Vector3[] startPoses = new Vector3[MaxHorizontalPlatforms];
for (int i = 0; i < MaxHorizontalPlatforms; i++)
{
startPoses[i] = new Vector3(leftBoader + (PositionIncrement * i), bottomeBoarder, 0f);
if (startPoses[i].x % PositionIncrement != 0f || startPoses[i].y % PositionIncrement != 0f)
Debug.Log("Start Pos " + i + " is Invalid");
}
int checkIndex = 0;
do
{
checkIndex = Random.Range(0, MaxHorizontalPlatforms);
if (startPosTrackers[checkIndex])
{
startPosTrackers[checkIndex] = !startPosTrackers[checkIndex];
break;
}
} while (!startPosTrackers[checkIndex]);
return startPoses[checkIndex];
}
private bool CheckForPlatform(Vector3 checkPos)
{
GameObject[] platforms = GameObject.FindGameObjectsWithTag("Platform");
foreach (GameObject platform in platforms)
{
if (platform.transform.position == checkPos)
{
return false;
}
}
return true;
}
private Vector3 GetMove()
{
int index = 0;
Vector3[] possibleMoves = new Vector3[5];
//Pos 1 (bottom Left)
if (xCheck - PositionIncrement >= leftBoader)
{
Vector3 PositionCheck = new Vector3(xCheck - PositionIncrement, yCheck, 0f);
if (CheckForPlatform(PositionCheck))
{
possibleMoves[index] = PositionCheck;
index++;
}
}
//Pos 2 (upper Left)
if (xCheck - PositionIncrement >= leftBoader && yCheck + PositionIncrement <= topBoader)
{
Vector3 PositionCheck = new Vector3(xCheck - PositionIncrement, yCheck + PositionIncrement, 0f);
if (CheckForPlatform(PositionCheck))
{
possibleMoves[index] = PositionCheck;
index++;
}
}
//Pos 3 (Straight Up)
if (yCheck + PositionIncrement <= topBoader)
{
Vector3 PositionCheck = new Vector3(xCheck, yCheck + PositionIncrement, 0f);
if (CheckForPlatform(PositionCheck))
{
possibleMoves[index] = PositionCheck;
index++;
}
}
//Pos 4 (Upper Right)
if (xCheck + PositionIncrement <= rightBoarder && yCheck + PositionIncrement <= topBoader)
{
Vector3 PositionCheck = new Vector3(xCheck + PositionIncrement, yCheck + PositionIncrement, 0f);
if (CheckForPlatform(PositionCheck))
{
possibleMoves[index] = PositionCheck;
index++;
}
}
//Pos 5 (Bottom Right)
if (xCheck + PositionIncrement <= rightBoarder)
{
Vector3 PositionCheck = new Vector3(xCheck + PositionIncrement, yCheck, 0f);
if (CheckForPlatform(PositionCheck))
{
possibleMoves[index] = PositionCheck;
index++;
}
}
int choice = Random.Range(1, index);
Vector3 move = possibleMoves[choice];
return move;
}
public void GenerateStartBoard()
{
for (int i = 0; i < NumberOfTrackers; i++)
{
Vector3 startPos = FindStartPosition();
GenerateTracker(startPos);
}
}
private void GenerateTracker(Vector3 startPos)
{
int FailsafeCounter = 0;
xCheck = startPos.x;
yCheck = startPos.y;
GameObject newPlat = Instantiate(platform);
newPlat.transform.position = new Vector3(xCheck, yCheck, 0f);
while (yCheck <= topBoader - PositionIncrement && FailsafeCounter <= 10)
{
Vector3 move = GetMove();
xCheck = move.x;
yCheck = move.y;
newPlat = Instantiate(platform);
newPlat.transform.position = new Vector3(xCheck, yCheck, 0f);
FailsafeCounter++;
}
}
public void ClearBoard()
{
GameObject[] platforms = GameObject.FindGameObjectsWithTag("Platform");
foreach(GameObject platform in platforms)
{
DestroyImmediate(platform);
}
}
}
Custom Inspector Script
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(GameGenerator))]
public class GameGeneratorInspector : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
GameGenerator gGen = (GameGenerator)target;
if (GUILayout.Button("Generate Start Board"))
{
gGen.GenerateStartBoard();
}
if (GUILayout.Button("Clear Board"))
{
gGen.ClearBoard();
}
}
}
Answer by Bunny83 · Mar 11, 2018 at 10:25 AM
This loop:
do
{
checkIndex = Random.Range(0, MaxHorizontalPlatforms);
if (startPosTrackers[checkIndex])
{
startPosTrackers[checkIndex] = !startPosTrackers[checkIndex];
break;
}
} while (!startPosTrackers[checkIndex]);
will cause a Hang when all your "startPosTrackers" boolean values are false. In that case you can never leave that loop. It's generally a bad implementation to re-roll a random number until you hit an unused slot. If you actually ensure that you never try to pull more startpositions that you actually have "true" values in the list it may work but the performance goes down exponentially the more elements turn false. If you have an array with 100 elements and only one is left it would take ages to randomly hit that one element.
You want to use some sort of List where you can simply remove used elements. That way you always roll only over the remaining elements. Also you can immediately see that there are no more remaining elements and terminate.
Keep in mind that editor scripts do change the values of your script permanentally. I don't see where you actually set your boolean values to true.
Answer by LightAxe2402 · Mar 11, 2018 at 04:09 PM
Okay cool, That was indeed the problem. Thank you for pointing that out! I'm still new to unity so still learning lol. Its an array of just 5 start position elements that I set in the editor. Since they are only used in the start code they aren't usually reset cause they are only usually used once per game but I will fix that now. Thank you again!