BevvyOfFun
BevvyOfFun

Reputation: 11

How to ensure that each object is instantiated an even number of times?

I have been using the following code to instantiate 9 gameObjects. It works beautifully, but I want to be able to ensure that each object is instantiated an even number of times. Does anyone know how to do this? Thanks in advance for any help you can give.

public int width = 10;
public int height = 10;
public GameObject[] tilePrefabs;

void Start()
{
    GenerateLevel();
}

void GenerateLevel()
{
    for (int x = -10; x < width; x++)
    {
        for (int y = -4; y < height; y++)
        {
            for (int i = 0; i < tilePrefabs.Length; i++)
            {
                if (Random.value > 0.5f) // 50% chance to place a tile
                {
                    int randomIndex = Random.Range(0, tilePrefabs.Length);
                    Vector2 position = new Vector2(x, y);
                    Instantiate(tilePrefabs[randomIndex], position, Quaternion.identity);
                }
            }
        }
    }
}

void FixedUpdate()
{
    if ((GameControl.control.matches >= 69) && (GameControl.control.matches < 207))
    {
        SceneManager.LoadScene("Level2");
    }
}

I could not find a way to ensure each GameObject appears an even number of times, which means that unused objects remain after any operation that is implemented.

Upvotes: 1

Views: 68

Answers (2)

derHugo
derHugo

Reputation: 90814

I assume by even number you rather mean equal so all 9 items are placed the same amount of times. If you actually meant even then simply adjust the amountPerType below accordingly. If it's supposed to be exactly 2 anyway it should be trivial.

I think it would be easier to go the other way round:

  • iterate the fix amount of tiles you want to place
  • then randomly pick a location
  • keep track of taken locations
  • retry until you find an empty spot

Somewhat like e.g.

// probably wouldn't want to hard code the 10 and 4 .. and call the width and height something else
// probably more like min and max
var totalTiles = (width + 10) * (height + 4);
// Percentage of tiles to fill
var totalMaxAmount = Mathf.FloorToInt(totalTiles * 0.5f);
// ensure each type is placed equal amount of times
var amountPerType = totalMaxAmount / tilePrefabs.Length;
// if additionally you actually wanted to ensure even amount
//amountPerType = 2 * (amountPerType / 2);

// Keep track of occupied spots
var takenSpots = new HashSet<Vector2Int>();

// iterate all types
for (int i = 0; i < tilePrefabs.Length; i++)
{
    // iterate for the amount to place
    for(var n = 0; n < amountPerType; n++)
    {
        // find a random spot that is not yet occupied
        // this is the lazy version .. as your field is rather limited you could even
        // create a list with all available spots and then randomize that
        // and then simply access the next one - would be deterministic
        Vector2Int randomSpot;
        do
        {
            randomSpot = new Vector2Int(Random.Range(-10, width), Random.Range(-4; height);
        }
        while(takenSpots.Contains(randomSpot));

        // track the chosen spot
        takenSpots.Add(randomSpot);

        // and finally place your object here
        Instantiate(tilePrefabs[i], (Vector2)randomSpot, Quaternion.identity);
    }
}

Upvotes: 1

RadioSpace
RadioSpace

Reputation: 952

so ...

essentially you want to create half of your random indexes then repeat it.

it won't matter how many times an index is entered cause once you repeat the list, all quantities will be even.

if you need more guidance or a firm example, just ask. but for starters you'll need the first list doubled then maybe randomize that list so it's not just a doubled pattern.

Upvotes: 0

Related Questions