Search code examples
c#unity-game-engineinstantiation

Unity randomiser generating results in a non-random gradient


I'm using code from the tutorial series "make a game" by Sebastian Lague and so far everything has been easily adapted to the new versions of unity. However on Episode 9, I have become unstuck. I have adapted the code for the map generator to get it to compile in my version of unity, 2019.3.11f1. However, the random map generation seems to bias towards lowest coordinated of the map.

My Gen results:

My Gen

What it should look like:

[target[2]

This code is the map generator script it is placed on an empty in the world and adds cubes as obstacles, provided with some prefabs.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;



public class MapGenerator : MonoBehaviour
{
    public Transform tilePrefab;
    public Vector2 mapSize;
    public int seed = 10;
    public Transform obstaclePrefab;
    public int obstacleCount = 10;



    [Range(0, 1)]
    public float outlinePercent;  // Cotrols scale of tiles 

    List<Coord> allTileCoords;
    Queue<Coord> shuffledTileCoords;

    private void Start()
    {
        GenerateMap();
    }


    public void GenerateMap()
    {

        allTileCoords = new List<Coord>();
        for (int x = 0; x < mapSize.x; x++)
        {
            for (int y = 0; y < mapSize.y; y++)
            {
                allTileCoords.Add(new Coord(x, y)); //iterate through mapSize adding tiles
            }
        }
        shuffledTileCoords = new Queue<Coord>(Utility.ShuffleArray(allTileCoords.ToArray(), seed)); //shuffled array of tiles coords

        string holderName = "Generated Map";                 //Added for the editor script
        if (GameObject.Find(holderName))                     //Added for the editor script
        {                                                    //Added for the editor script
            DestroyImmediate(GameObject.Find(holderName));   //Added for the editor script
        }                                                    //Added for the editor script

        Transform mapHolder = new GameObject(holderName).transform; //This is only neccessary because of the editor script
        mapHolder.parent = transform; //This is only neccessary because of the editor script

        for (int x = 0; x < mapSize.x; x++)
        {
            for (int y = 0; y < mapSize.y; y++)
            {
                Vector3 tilePosition = relativeToSpacial(x, y); //converts grid x,y data to real spatial coords
                Transform newTile = Instantiate(tilePrefab, tilePosition, Quaternion.Euler(Vector3.right * 90)) as Transform; //instantiates tile in loctaion from rel to spatial func with 90 rotation
                newTile.localScale = Vector3.one * (1 - outlinePercent); //scales down tiles to leave a outline
                newTile.parent = mapHolder;
            }
        }

        for (int i = 0; i < obstacleCount; i++)
        {
            Coord randomCoord = GetRandomCoord();
            Vector3 obstaclePosition = relativeToSpacial(randomCoord.x, randomCoord.y);
            Transform newObstacle = Instantiate(obstaclePrefab, obstaclePosition + Vector3.up * .5f, Quaternion.identity) as Transform;
            newObstacle.parent = mapHolder;
        }
    }

    Vector3 relativeToSpacial(int x, int y)
    {
        return new Vector3(-mapSize.x / 2 + .5f + x, 0, -mapSize.y / 2 + .5f + y);
    }


    public Coord GetRandomCoord()
    {
        Coord randomCoord = shuffledTileCoords.Dequeue();
        shuffledTileCoords.Enqueue(randomCoord);
        //print("|| " + randomCoord.x + " || " + randomCoord.y + " ||");
        return randomCoord;
    }

    public struct Coord
    {
        public int x;
        public int y;

        public Coord(int _x, int _y)
        {
            x = _x;
            y = _y;
        }
    }
}

This is the code from Utility.ShuffleArray which is my custom function for shuffling arrays.

using System.Collections;
using System.Collections.Generic;


public static class Utility
{
    public static T[] ShuffleArray<T>(T[] array, int seed)
    {
        System.Random prng = new System.Random(seed);
        for (int i =0; i < array.Length -1; i++)
        {
            int randomIndex = prng.Next(i, array.Length);
            T tempItem = array[randomIndex];
            array[randomIndex] = array[i];
        }
        return array;
    }
}

Any help appreciated.


Solution

  • int randomIndex = prng.Next(i, array.Length);
    

    You are incrementing the clamp on your rng in this line in your for loop, so it becomes increasingly bias to the end of the array, also I added code to do a swap of positions rather than duplicate of position try something like this

    int randomIndex = prng.Next(0, array.Length);
    T tempItem = array[randomIndex];
    T tempItemTwo = array[i];
    array[randomIndex] = array[i];
    array[i] = tempItemTWo;
    

    if that doesnt work also try:

    int randomIndex = prng.Next(i, array.Length);
    T tempItem = array[randomIndex];
    T tempItemTwo = array[i];
    array[randomIndex] = array[i];
    array[i] = tempItemTWo;