Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice

Need Help with Random Level Generation

Discussion in 'Scripting' started by BudBroesky, Aug 22, 2015.

  1. BudBroesky

    BudBroesky

    Joined:
    Nov 11, 2013
    Posts:
    15
    Hey! So I've designed a basic random level generator, it worked perfectly... however some blocks were wasted as the program wasn't previously checking if a block was in the place it wanted to create one in.

    Here's how the program thinks:
    • Creates a Starting Block
    • Gets a random direction to place next block
    • Attempts to validate that that spot is free
    • If so, it places the object
    • If not it (is supposed to) moves to the farthest point in that direction beside another block, then places the block.
    • Adds to the number of blocks added
    • Waits the user-set amount (for visual-watching sake)
    • Then going back to the 2nd point, rinse and repeat.

    Here's the issue, Im getting the error of Object reference not set to an instance of an object, which I've gotten and know (usually) how to fix... but I instantiate the object it's trying to reference before the function is called, so I don't understand why the program can't reach the object.

    I'm not necessarily looking for advice on how to re-write the whole program, just how to fix this particular issue. I'd ideally like to have each individual block check whether it's on top of another and move itself, however I'd like to see this work as I don't see a reason is shouldn't.

    Enough typing, my fingers hurt... here's my code:

    *Yes I realize a lot of variables aren't used yet or don't do anything, it's still a work in progress...


    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class GenerationMachine : MonoBehaviour {
    5.     [Header("Generation Machine:")]
    6.     public bool isDone = false;
    7.     [Range(1, 100)]
    8.     public int levelWidth;
    9.     [Range(1, 100)]
    10.     public int levelHeight;
    11.     [Range(1, 500)]
    12.     public int numberOfTiles;
    13.     [Range(0.0f, 5.0f)]
    14.     public float placementSpeed;
    15.  
    16.     [Header("Objects:")]
    17.     public GameObject player = null;
    18.     public GameObject cam = null;
    19.     public GameObject floorObject = null;
    20.     public GameObject wallObject = null;
    21.     public GameObject enemyObject = null;
    22.  
    23.     [Header("Raycasting Checks:")]
    24.     public Transform[] raycastPoints;
    25.     public bool leftFree = true;
    26.     public bool rightFree = true;
    27.     public bool upFree = true;
    28.     public bool downFree = true;
    29.  
    30.     [Header("Misc. Variables:")]
    31.     public bool canPlace = true;
    32.     public bool keepGoing = true;
    33.     public bool spawnPlayerAfter = true;
    34.     public int placedBlocks = 0;
    35.     public GameObject[] floorBlocks;
    36.     public enum direction {left, right, up, down};
    37.     public direction placementDirection;
    38.     private int values = System.Enum.GetValues(typeof(direction)).Length;
    39.  
    40.     // Use this for initialization
    41.     void Start () {
    42.         floorBlocks = new GameObject[numberOfTiles];
    43.         floorBlocks [0] = floorObject;
    44.         Instantiate(floorBlocks[0], transform.position, Quaternion.identity);
    45.         placedBlocks++;
    46.         FirstCheck (placedBlocks);
    47.     }
    48.    
    49.     // Update is called once per frame
    50.     void FixedUpdate () {
    51.  
    52.     }
    53.  
    54.     void FirstCheck (int blockID)
    55.     {
    56.         if (placedBlocks != numberOfTiles) {
    57.             placementDirection = (direction)Random.Range (0, values);
    58.             cam.transform.position = transform.position;
    59.             switch (placementDirection) {
    60.             case direction.left:
    61.                 CheckPos(-1, 0);
    62.                 if (canPlace && keepGoing) {
    63.                     floorBlocks [blockID] = floorObject;
    64.                     PlaceBlock (placementDirection);
    65.                 } else {
    66.                     LeftSkip();
    67.                 }
    68.                 break;
    69.             case direction.right:
    70.                 CheckPos(1, 0);
    71.                 if (canPlace && keepGoing) {
    72.                     floorBlocks [blockID] = floorObject;
    73.                     PlaceBlock (placementDirection);
    74.                 } else {
    75.                     RightSkip();
    76.                 }
    77.                 break;
    78.             case direction.up:
    79.                 CheckPos(0, 1);
    80.                 if (canPlace && keepGoing) {
    81.                     floorBlocks [blockID] = floorObject;
    82.                     PlaceBlock (placementDirection);
    83.                 } else {
    84.                     UpSkip();
    85.                 }
    86.                 break;
    87.             case direction.down:
    88.                 CheckPos(0, -1);
    89.                 if (canPlace && keepGoing) {
    90.                     floorBlocks [blockID] = floorObject;
    91.                     PlaceBlock (placementDirection);
    92.                 } else {
    93.                     DownSkip();
    94.                 }
    95.                 break;
    96.             }
    97.         } else {
    98.             isDone = true;
    99.             if (spawnPlayerAfter)
    100.             {
    101.                 spawnPlayerAfter = false;
    102.                 player.transform.position = floorBlocks[0].transform.position;
    103.                 cam.transform.position = floorBlocks[0].transform.position;
    104.             }
    105.         }
    106.     }
    107.  
    108.     //Places block in given direction
    109.     void PlaceBlock (direction dir)
    110.     {
    111.         switch (dir)
    112.         {
    113.         case direction.left:
    114.             transform.position -= new Vector3(1, 0, 0);
    115.             Instantiate(floorBlocks[placedBlocks], transform.position, Quaternion.identity);
    116.             placedBlocks++;
    117.             StartCoroutine(Wait());
    118.             break;
    119.         case direction.right:
    120.             transform.position += new Vector3(1, 0, 0);
    121.             Instantiate(floorBlocks[placedBlocks], transform.position, Quaternion.identity);
    122.             placedBlocks++;
    123.             StartCoroutine(Wait());
    124.             break;
    125.         case direction.up:
    126.             transform.position -= new Vector3(0, 1, 0);
    127.             Instantiate(floorBlocks[placedBlocks], transform.position, Quaternion.identity);
    128.             placedBlocks++;
    129.             StartCoroutine(Wait());
    130.             break;
    131.         case direction.down:
    132.             transform.position += new Vector3(0, 1, 0);
    133.             Instantiate(floorBlocks[placedBlocks], transform.position, Quaternion.identity);
    134.             placedBlocks++;
    135.             StartCoroutine(Wait());
    136.             break;
    137.         }
    138.     }
    139.  
    140.     //Checks whether a block is in the spot they want to move to
    141.     void CheckPos (float xAddition, float yAddition)
    142.     {
    143.         keepGoing = false;
    144.  
    145.         for (int i = 0; i <= placedBlocks; i++)
    146.         {
    147.             if (!keepGoing && floorBlocks[i].transform.position == new Vector3(transform.position.x + xAddition, transform.position.y + yAddition, 0))
    148.             {
    149.                 canPlace = false;
    150.                 keepGoing = true;
    151.                 break;
    152.             } else if (i == placedBlocks)
    153.             {
    154.                 canPlace = true;
    155.                 keepGoing = true;
    156.             }
    157.         }
    158.     }
    159.  
    160.     //Finds the farthest point in the given direction, then moves the Controller there to carry on "untrapped".
    161.     void LeftSkip ()
    162.     {
    163.         float xToBeat = 0;
    164.         bool keepGoing = false;
    165.         for (int i = 0; i == placedBlocks; i++)
    166.         {
    167.             if (floorBlocks[i].transform.position.x < xToBeat && floorBlocks[i].transform.position.y == transform.position.y)
    168.             {
    169.                 xToBeat = floorBlocks[i].transform.position.x;
    170.             }
    171.  
    172.             if (i == placedBlocks)
    173.             {
    174.                 keepGoing = true;
    175.             }
    176.         }
    177.  
    178.         transform.position = new Vector3 (xToBeat, transform.position.y, 0);
    179.         FirstCheck (placedBlocks);
    180.     }
    181.  
    182.     void RightSkip ()
    183.     {
    184.         float xToBeat = 0;
    185.         bool keepGoing = false;
    186.         for (int i = 0; i == placedBlocks; i++)
    187.         {
    188.             if (floorBlocks[i].transform.position.x > xToBeat && floorBlocks[i].transform.position.y == transform.position.y)
    189.             {
    190.                 xToBeat = floorBlocks[i].transform.position.x;
    191.             }
    192.            
    193.             if (i == placedBlocks)
    194.             {
    195.                 keepGoing = true;
    196.             }
    197.         }
    198.        
    199.         transform.position = new Vector3 (xToBeat, transform.position.y, 0);
    200.         FirstCheck (placedBlocks);
    201.     }
    202.  
    203.     void UpSkip ()
    204.     {
    205.         float yToBeat = 0;
    206.         bool keepGoing = false;
    207.         for (int i = 0; i == placedBlocks; i++)
    208.         {
    209.             if (floorBlocks[i].transform.position.y > yToBeat && floorBlocks[i].transform.position.x == transform.position.x)
    210.             {
    211.                 yToBeat = floorBlocks[i].transform.position.y;
    212.             }
    213.            
    214.             if (i == placedBlocks)
    215.             {
    216.                 keepGoing = true;
    217.             }
    218.         }
    219.        
    220.         transform.position = new Vector3 (transform.position.x, yToBeat, 0);
    221.         FirstCheck (placedBlocks);
    222.     }
    223.  
    224.     void DownSkip ()
    225.     {
    226.         float yToBeat = 0;
    227.         bool keepGoing = false;
    228.         for (int i = 0; i == placedBlocks; i++)
    229.         {
    230.             if (floorBlocks[i].transform.position.y < yToBeat && floorBlocks[i].transform.position.x == transform.position.x)
    231.             {
    232.                 yToBeat = floorBlocks[i].transform.position.y;
    233.             }
    234.            
    235.             if (i == placedBlocks)
    236.             {
    237.                 keepGoing = true;
    238.             }
    239.         }
    240.        
    241.         transform.position = new Vector3 (transform.position.x, yToBeat, 0);
    242.         FirstCheck (placedBlocks);
    243.     }
    244.  
    245.     IEnumerator Wait ()
    246.     {
    247.         yield return new WaitForSeconds(placementSpeed);
    248.         FirstCheck (placedBlocks);
    249.     }
    250. }
     
  2. Duugu

    Duugu

    Joined:
    May 23, 2015
    Posts:
    241
    I guess it would be helpful to know the line number and not only the error. :)
    Could you please post the full error text?
     
    Kiwasi likes this.
  3. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    So you should be able to throw in a few debugs and tell us exactly what is null.
     
  4. HiddenMonk

    HiddenMonk

    Joined:
    Dec 19, 2014
    Posts:
    987
    The error was being thrown at line 147. It was due to you doing "for (int i = 0; i <= placedBlocks; i++)" Change the <= to just < and the error goes away. However, this opens up other errors.
     
    Kiwasi likes this.
  5. BudBroesky

    BudBroesky

    Joined:
    Nov 11, 2013
    Posts:
    15
    I figured that out, however now when I use the debugger (or if I don't) it's only iterating through the whole process once, where it used to do it over and over...