Hello,
apologies in advance if it’s a question that has been asked before by others. I have tried to implement the suggested methods but it still did not work. I am trying to make sure there is no overlap when the cards are spawned.
The scene produces some cards, 10 here in the picture below, one by one, in random positions. When the button is clicked, it produces new cards again.
For anyone interested in checking the working code that produces the behavior described:
public class Overlap : MonoBehaviour
{
float xRandomPos, yRandomPos;
Vector3 finalRandomPos;
public int numToGenerate;
public List<GameObject> listOfObjects;
public GameObject background;
MeshCollider borders;
void Start()
{
borders = background.GetComponent<MeshCollider>();
WrappedCoroutine();
}
/// <summary>
/// For the Button to click
/// </summary>
public void WrappedCoroutine()
{
StartCoroutine(Coroutine());
}
/// <summary>
/// Main method
/// </summary>
/// <returns></returns>
public IEnumerator Coroutine()
{
//coroutine
WaitForSeconds wait = new WaitForSeconds(1f);
//what to generate
int randomItemFromListIndex;
GameObject randomItemFromList;
for (int i = 0; i < numToGenerate; i++)
{
//the object
randomItemFromListIndex = Random.Range(0, listOfObjects.Count);
randomItemFromList = listOfObjects[randomItemFromListIndex];
//where
xRandomPos = Random.Range(borders.bounds.min.x, borders.bounds.max.x);
yRandomPos = Random.Range(borders.bounds.min.y, borders.bounds.max.y);
finalRandomPos = new Vector3(xRandomPos, yRandomPos, 0f);
//setUpperLower(finalRandomPos);
//randomItemFromList.transform.rotation same as Quaternion.identity?
Instantiate(randomItemFromList, finalRandomPos, Quaternion.identity);
yield return wait;
}
}
/// <summary>
/// Restarts the current scene when the button is clicked
/// </summary>
public void Restart()
{
SceneManager.LoadScene("Overlap");
}
}
Now, this below was the first attempt to modify the same code, so that it would not overlap, and it did not work:
public class Overlap : MonoBehaviour
{
//------------------------------new changes in attempt to avoid overlappping------------------------
public Collider2D[] colliders;
public float radius;
int safetyNet = 0;
//---------------------------------------------------------------------------------------------------
float xRandomPos, yRandomPos;
Vector3 finalRandomPos;
public int numToGenerate;
public List<GameObject> listOfObjects;
public GameObject background;
MeshCollider borders;
void Start()
{
borders = background.GetComponent<MeshCollider>();
WrappedCoroutine();
}
/// <summary>
/// For the Button to click
/// </summary>
public void WrappedCoroutine()
{
StartCoroutine(Coroutine());
}
/// <summary>
/// Main method
/// </summary>
/// <returns></returns>
public IEnumerator Coroutine()
{
//coroutine
WaitForSeconds wait = new WaitForSeconds(1f);
//what to generate
int randomItemFromListIndex;
GameObject randomItemFromList;
for (int i = 0; i < numToGenerate; i++)
{
//the object
randomItemFromListIndex = Random.Range(0, listOfObjects.Count);
randomItemFromList = listOfObjects[randomItemFromListIndex];
//where
xRandomPos = Random.Range(borders.bounds.min.x, borders.bounds.max.x);
yRandomPos = Random.Range(borders.bounds.min.y, borders.bounds.max.y);
finalRandomPos = new Vector3(xRandomPos, yRandomPos, 0f);
//------------------------------new changes in attempt to avoid overlappping------------------------
if (PreventOverlap(finalRandomPos))
{
Instantiate(randomItemFromList, finalRandomPos, Quaternion.identity);
yield return wait;
}
//---------------------------------------------------------------------------------------------------
}
}
//------------------------------new changes in attempt to avoid overlappping------------------------
bool PreventOverlap(Vector3 finalRandomPos)
{
//NB: it's an array
colliders = Physics2D.OverlapCircleAll(transform.position, radius);
for (int i = 0; i < colliders.Length; i++)
{
//checking the bounds of each collider and
//return false if the intended generating position falls within the bounds
Vector3 centerPoint = colliders[i].bounds.center;
float width = colliders[i].bounds.extents.x;
float height = colliders[i].bounds.extents.y;
//from which the main points can be derived
float left = centerPoint.x - width;
float right = centerPoint.x + width;
float top = centerPoint.y - height;
float bottom = centerPoint.y + height;
//if it's falling within the left and right or top and bottom
if (finalRandomPos.x >= left && finalRandomPos.x <= right)
{
//not here
return false;
}
if(finalRandomPos.y >= top && finalRandomPos.y <= bottom)
{
//not here
return false;
}
}
return true;
}
//-----------------------------------------------------------------------------------------
/// <summary>
/// Restarts the current scene when the button is clicked
/// </summary>
public void Restart()
{
SceneManager.LoadScene("Overlap");
}
}
The code above does not produce any changes to the program. Any suggestions as to where it might have gone wrong? Alternatively, this below again is another unsuccessful attempt to modify the code:
public class Overlap : MonoBehaviour
{
//------------------------------new changes in attempt to avoid overlappping------------------------
//min------of the rectangle we want to check for collision
Vector2 upperLeft = new Vector2();
//max------of the rectangle we want to check for collision
Vector2 lowerRight = new Vector2();
//we will set the appropriate x and y for these when the time is right: more efficient from a memory perspective
float xRandomPos, yRandomPos, halfWidth, halfHeight;
//---------------------------------------------------------------------------------------------------
Vector3 finalRandomPos;
public int numToGenerate;
public List<GameObject> listOfObjects;
public GameObject background;
MeshCollider borders;
void Start()
{
borders = background.GetComponent<MeshCollider>();
WrappedCoroutine();
}
/// <summary>
/// For the Button to click
/// </summary>
public void WrappedCoroutine()
{
StartCoroutine(Coroutine());
}
/// <summary>
/// Main method
/// </summary>
/// <returns></returns>
public IEnumerator Coroutine()
{
//coroutine
WaitForSeconds wait = new WaitForSeconds(1f);
//what to generate
int randomItemFromListIndex;
GameObject randomItemFromList;
int i = 1;
while(Physics2D.OverlapArea(upperLeft, lowerRight) != null && i< numToGenerate)
{
//the object
randomItemFromListIndex = Random.Range(0, listOfObjects.Count);
randomItemFromList = listOfObjects[randomItemFromListIndex];
//where
xRandomPos = Random.Range(borders.bounds.min.x, borders.bounds.max.x);
yRandomPos = Random.Range(borders.bounds.min.y, borders.bounds.max.y);
finalRandomPos = new Vector3(xRandomPos, yRandomPos, 0f);
//------------------------------new changes in attempt to avoid overlappping------------------------
setUpperLower(finalRandomPos);
//---------------------------------------------------------------------------------------------------
Instantiate(randomItemFromList, finalRandomPos, Quaternion.identity);
yield return wait;
i++;
}
}
//------------------------------new changes in attempt to avoid overlappping------------------------
void setUpperLower(Vector3 pos)
{
upperLeft.x = pos.x - halfWidth;
upperLeft.y = pos.y - halfHeight;
lowerRight.x = pos.x + halfWidth;
lowerRight.y = pos.y + halfHeight;
}
//-----------------------------------------------------------------------------------------
/// <summary>
/// Restarts the current scene when the button is clicked
/// </summary>
public void Restart()
{
SceneManager.LoadScene("Overlap");
}
}
Unlike the previous attempt, the code below does not produce any card at all.
Any suggestion as to how I can modify the code and where I am understanding this wrong would be much appreciated!