- Home /
Why does this script sometimes not complete its task?
First of all, I am sorry for the huge code dump. In my endless testing I have created something that needs to be refactored badly. I am still very new to programming and due to low funds I am somewhat self taught.
|
I Have attached the code and video link below because I have been trying to create a bubble shooter game similar to Bubble Witch Saga. At the moment The program works but taking what ever bubble I click on and then it checks the surrounding bubbles to find any that share the same colour, and then proceeds to check the newly selected bubbles for any more to match with before finally deleting them.
|
I don't understand why sometimes it will leave some of the bubbles behind and why sometimes it wont select from the end on the 'row' but will work if i click on the middle bubble. Does anyone know what could be causing this?
|
Please find the video here: https://youtu.be/LA_LjN0Jovg
|
Below is the script for this program:
|
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LevelManager : MonoBehaviour
{
public GameObject[] anchorPoints; // An Array Containing all the point on which the bubbles will spawn. Set in Inspector
public GameObject bubble; //A variable containing a reference to the Bubble Prefab that will be Instantiated. Set in Inspector
public List<GameObject> triggeredBubbles = new List<GameObject>(); // Creates an empty list called triggeredBubbles.
// Start is called before the first frame update
void Start()
{
for (int i = 0; i < anchorPoints.Length; i++) // for each item in the anchorPoints array:
{
Vector3 pos = anchorPoints[i].transform.position; //Assign the anchor point's position to a temp variable called pos
GameObject newBubble = Instantiate(bubble, pos,Quaternion.identity); //create a clone of the bubble prefab, at the position currently in pos with no changes to rotation. And assign the new object to the variable newBubble
newBubble.name = ("Bubble " + i); //Renames the object held in newBubble to 'Bubble x', where x is its location in the anchorPoint array
SetColour(newBubble); //Run the SetColour Function passing the current newBubble through.
}
}
// Update is called once per frame
void Update()
{
//Player Controller ################################################################################3
if (Input.GetMouseButtonDown(0))
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
if (hit.collider.tag != null)
{
CheckConnected(hit.collider.gameObject);
}
}
}
}
// MY FUNCTIONS ######################################################################################3
public void SetColour(GameObject newBubble)
{
int id = Random.Range(0, 4);
if (id == 0)
{
newBubble.GetComponent<MeshRenderer>().material.color = Color.red;
newBubble.tag = "red";
}
if (id == 1)
{
newBubble.GetComponent<MeshRenderer>().material.color = Color.blue;
newBubble.tag = "blue";
}
if (id == 2)
{
newBubble.GetComponent<MeshRenderer>().material.color = Color.green;
newBubble.tag = "green";
}
if (id == 3)
{
newBubble.GetComponent<MeshRenderer>().material.color = Color.magenta;
newBubble.tag = "magenta";
}
}
public void CheckConnected(GameObject newBubble)
{
int numberOfBubbles = 0;
Collider[] attached = Physics.OverlapSphere(newBubble.transform.position, 0.55f);
foreach (Collider col in attached)
{
string colliderName = col.name;
if (col.tag == newBubble.tag)
{
if (triggeredBubbles.Contains(col.gameObject) == false) { triggeredBubbles.Add(col.gameObject); }
else { return; }
CheckConnected(col.gameObject);
numberOfBubbles += 1;
}
}
if (triggeredBubbles.Count >= 3)
{
DestroyTriggedBubbles();
}
else
{
triggeredBubbles = new List<GameObject>();
}
}
private void DestroyTriggedBubbles()
{
foreach(GameObject bubble in triggeredBubbles)
{
Destroy(bubble);
}
triggeredBubbles = new List<GameObject>();
}
}
Are you sure you wan to use "return" on 85 line when iterating through bubbles you found? I suppose it would be better to add all nearby bubbles to the list (with the correct tag) and then use recursive thing for all of them? Because now it seems like if you have circle of bubbles, for example, your algorithm could just go away from the circle center without adding some bubbles to the list.
Hey @Slaesh, I had thought it might be something to do with that. Do you have any idea what else I should you in its place?
!
If I try to run it without return, I get an infinite loop, and Unity hangs
Answer by SunnyChow · Aug 23, 2021 at 03:35 AM
This is what i see...
Collider[] attached = Physics.OverlapSphere(newBubble.transform.position, 0.55f);
Let's say it gets an Array of 3 balls : [(matched), (not matched), (matched)]
When checking the 1st ball, it's matched, so the ball is added to the List. When checking the 2nd ball, it doesn't match, so the function returns. And the function doesn't check the third ball.
Here is an idea. You make two List: checkList and matchList. You make a while loop that always check the first ball in checkList and then remove the first ball in checkList. if it's a match, add the ball to matchList, and do Physics.OverlapSphere() to add new balls to checkList (but make sure the new balls don't already exist in checkList and matchList)
EDIT If you want more improvement, maybe you should make the game based on a 2d Array, instead of checking ball via the physics engine. Also, using Queue for checkList maybe better.