Hey some might have seen my issue with arrays earlier, however Im now having issues with lists, that again, not sure whats going on. Ive posted the code below. Error is on line "116, with a null Reference Exception, however it seems to loop through, according to debugs fine, the first time, its only the second time that it fails.
For easiness sake, I’ve also included the code from the TileContainer class.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Tilemaps;
public class WaveFunctionCollapse : MonoBehaviour
{
[SerializeField] Tilemap InputMap; //The input tilemap to take
[SerializeField] Tilemap outputMap; //Where the output will be going
public TileBase[] allTiles; //This is needed to take a 1D array of tiles form the inputTilemap.
public BoundsInt bounds; //The area of the tilemap. needed to lopop through the 1D array, allTiles, to put into our 2D array.
public TileBase[,] inputTiles; //A 2D array that we create to take the info from each of our tiles before transfering it to your 2D araay of containers. A later update could likely remove this.
public TileContainer[,] inputMapContainer; //Our 2D array that we will be using to go through each tile, adding neighbours, before recombining into a list.
public List<TileContainer> AllPossibleTiles; //Our list that we will be using for WFC itself. this will have the info of each tile, and what each possible neighbour can be.
//will need n editor button to run the script
// Start is called before the first frame update
void Start()
{
Run();
}
// Update is called once per frame
void Update()
{
}
void Run()
{
InputMap.CompressBounds(); //Sets the array to the area of the tiles, in case something went wrong.
bounds = InputMap.cellBounds;
TileBase[] allTiles = InputMap.GetTilesBlock(bounds); //the bounds above is used to get the tiles in this area.
inputTiles = new TileBase[bounds.size.x,bounds.size.y]; // creates our array of tiles in the right size.
inputMapContainer = new TileContainer[bounds.size.x, bounds.size.y]; //creating the size of the array so we can start intrializing the lists, and putting the info in
// nested for loop. We get a 1D array of elements when we call get the tiles, and to simplify the information we should have a 2d array.
for (int x = 0; x < bounds.size.x; x++)
for (int y = 0; y < bounds.size.y; y++)
{
if (allTiles[x + y * bounds.size.x] == null)
{
//The array should have no holes in it, but just in case.
Debug.Log("Null tile, will not work, location: " + x + " and " + y);
}
//This take the 2D array, and turns it into a 2D array.
inputTiles[x, y] = allTiles[x + y * bounds.size.x];
// Debug.Log(inputTiles[x, y].name + " this is a 2D array" + x + " " + y);
//All of these need to be initialized now, or they return errors later on. This is the easiest place for the input array.
//These are the tile itself, and each of its possible neighbours, plus all the tiles that can be in there, though this isnt used as of now.
inputMapContainer[x, y] = new TileContainer(inputTiles[x, y]);
inputMapContainer[x, y].possibleUpTiles = new List<TileBase>();
inputMapContainer[x, y].possibleDownTiles = new List<TileBase>();
inputMapContainer[x, y].possibleLeftTiles = new List<TileBase>();
inputMapContainer[x, y].possibleRightTiles = new List<TileBase>();
inputMapContainer[x, y].possibleTilesForThis = new List<TileBase>();
// Debug.Log(allTiles[x + y * bounds.size.x].name);
// inputMapContainer[x, y].SingleTile = inputTiles[x, y];
Debug.Log(inputMapContainer[x, y].SingleTile.name + " " + x + " " + y);
}
for (int x = 0; x < bounds.size.x; x++)
for (int y = 0; y < bounds.size.y; y++)
{
//This loop sets all the possible neighbours for each tile.
//In each iteration it checks the neighnbour next to it, to see if it is ourside the bounding box,
//and if it isnt, it gets that info from the array in that spot.
//This step is done after the last step is fully finished as, while it may have seemed like it would work in the last one,
//it simply doesnt due to the first tiles never being able to find what their neighbours have.
if (x + 1 < bounds.size.x)
{
inputMapContainer[x, y].possibleUpTiles.Add(inputMapContainer[x + 1, y].SingleTile);
Debug.Log("Added Up" + x + " " + y);
}
if (x - 1 >= 0)
{
inputMapContainer[x, y].possibleDownTiles.Add(inputMapContainer[x - 1, y].SingleTile);
Debug.Log("Added Down" + x + " " + y);
}
if (y - 1 >= 0)
{
inputMapContainer[x, y].possibleLeftTiles.Add(inputMapContainer[x, y - 1].SingleTile);
Debug.Log("Added Left" + x + " " + y);
}
if (y + 1 < bounds.size.y)
{
inputMapContainer[x, y].possibleRightTiles.Add(inputMapContainer[x, y + 1].SingleTile);
Debug.Log("Added Right" + x + " " + y);
}
}
//This step now needs to take each element of the array, and combine them into the list.
//To do this, we will check if a list contains elements from each part of the array, and if they are the same, we will add each neightbour to a list of each for that, checking again if any neihbours are the same
//
AllPossibleTiles = new List<TileContainer>();
foreach (TileContainer TileToCheckfrominput in inputMapContainer)
{
if (AllPossibleTiles == null)
{
Debug.Log("Not initialized");
AllPossibleTiles.Add(TileToCheckfrominput);
}
else
{
Debug.Log("NO Error before null");
var contains = AllPossibleTiles.Find(ListTiles => ListTiles.name == TileToCheckfrominput.name);
Debug.Log("NO Error after var null");
if (contains != null)
{
//if contains is true we need to add the
Debug.Log("Concat elements");
contains.possibleUpTiles.Union<TileBase>(TileToCheckfrominput.possibleUpTiles);
}
else
{
Debug.Log("Adding new element");
AllPossibleTiles.Add(TileToCheckfrominput);
Debug.Log("Error on add");
}
}
Debug.Log("Looped through fine");
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class TileContainer: MonoBehaviour
{
public TileBase SingleTile;
public List<TileBase> possibleUpTiles;
public List<TileBase> possibleDownTiles;
public List<TileBase> possibleLeftTiles;
public List<TileBase> possibleRightTiles;
public List<TileBase> possibleTilesForThis;
public bool hasBeenCollapsed = false;
public bool hasCollision = false;
public int collisionX;
public int collisionY;
public TileContainer(TileBase newTile)
{
SingleTile = newTile;
}
public TileContainer()
{
// This is needed for the output tiles so I can create them with no issues.
}
}