I found another way to do it.
Need to do multiple boolean check for completing level
Hi, so i'm doing a puzzle game where you need to push boxes to their areas to go to the next level, but i have 4 different types of boxes, so like the blue ones needs to go to the blue areas, red ones to red areas etc.
I saw that solution :
bool IsLevelComplete() {
BlueBox[] blueboxes = FindObjectsOfType<BlueBox>();
foreach (var bluebox in blueboxes) {
if (!bluebox.onBlueArea) return false;
}
return true;
}
but i can't find a way to make it work with the 4 different types at the same time. Thanks in advance.
Answer by Dangerface · Jun 09, 2020 at 05:38 AM
The FindObjectsOfType is very slow.
I would suggest to tag all you boxes with color tags - Then make goal colliders and with each a separate script and then check the color tag of objects entered in the goal collider has the corresponding color.
Example of goal collider:
public void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "Red" )
{
//Correct cube color
}
if (other.gameObject.tag != "Red" )
{
//Incorrect cube color
}
}
Answer by Arkonali · Jun 09, 2020 at 08:19 AM
@Dangerface I'm already doing that in another way
void TestForOnBlueArea()
{
GameObject[] blueAreas = GameObject.FindGameObjectsWithTag("BlueArea");
foreach (var blueArea in blueAreas)
{
if (transform.position.x == blueArea.transform.position.x && transform.position.y == blueArea.transform.position.y)
{
m_OnBlueArea = true;
return;
}
}
m_OnBlueArea = false;
}
What i'm looking for is to check if all the "m_On[Color]Area" are true in the scene, and if they are true, then send to my "bool IsLevelComplete" a true. So maybe i did not understood your answer but i think what i wrote just above is pretty much doing the same thing right ?
Ok I misunderstood then. If you already have the logic for seeing if the right boxes are in the right place, then you can check it with a simple if statement. $$anonymous$$ake a gameController object that listens to all the mOn[color]Area bools by referencing their scripts.
if(script1.m_On[Color1]Area && script2.m_On[Color2]Area && script3.m_On[Color3]Area && script4.m_On[Color4]Area )
{
//Win level
}
else
{
//Level not complete
}
@Dangerface So i tried doing this :
bool IsLevelComplete()
{
if (BlueBox.m_OnBlueArea && RedBox.m_OnRedArea && OrangeBox.m_OnOrangeArea && GreenBox.m_OnGreenArea)
{
Debug.Log("Done");
return true;
}
else
{
return false;
}
}
But I got the error "CS0120 C# An object reference is required for the non-static field, method, or property" And i can't seem to find a solution for this error that works for me.
Answer by tadadosi · Jun 09, 2020 at 10:46 AM
You need to use the concept of Inheritance in which you have a base class and any number of derived classes from that base class.
Using this idea you will have a base class called BoxBase
(or any other name you like) like this:
using UnityEngine;
public class BoxBase : MonoBehaviour
{
// protected so it can only be set by this base class or the derived classes
public bool IsOnArea { get { return _IsOnArea; } protected set { _IsOnArea = value; } }
// To expose a bool on the Inspector and to use internally
[SerializeField] protected bool _IsOnArea;
}
Then you can have any number of derived classes that can be called BoxBlue
, BoxRed
, and so on:
// Replace Monobehaviour with BoxBase to make it a derived class.
public class BoxBlue : BoxBase
{
private void Awake()
{
// on awake just for test purposes
_IsOnArea = true;
}
}
Lastly a simple LevelChecker
class that finds all the BoxBase
classes and use them to check the bool IsOnArea
:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LevelChecker : MonoBehaviour
{
private BoxBase[] boxes;
private void Awake()
{
boxes = FindObjectsOfType<BoxBase>();
}
private void Start()
{
if (CheckBoxes())
Debug.Log("Boxes are on their corresponding areas!");
}
private bool CheckBoxes()
{
for (int i = 0; i < boxes.Length; i++)
{
if (!boxes[i].IsOnArea)
return false;
}
return true;
}
}