First think of how many tile types you’re going to have. It would be ideal if you could use 255 as that would greatly conserve memory, but that is fairly inflexible. Let’s say that you won’t have more than 32k tile types. So, the type of your array will be an ushort. That stands for unsigned short, which is a data type that contains integers between 0 - 2^16 - 1.
Now, think about how large your map can be. Pokemon maps have more than 255 tiles in one dimension for sure, at least newer Pokemon games (unsure about older ones). So, your limits are going to also be 16-bit.
You can define a constant in some static script, which is what I recommend. To do that, create a static script which can hold your variables. And example of what I have would be this:
using UnityEngine;
public static class Constants
{
#region GAME_AMOUNT_CONSTANTS
public static int EventCount = 8;
public static int ItemCount = 4;
public static int AriaCount = 60;
public static int QuestItemCount = 8;
public static int NumberOfMaps = 2;
public static int NumberOfLanguages = 2;
public static int NumberOfVibrateParts = 30;
#endregion
}
I can access these numbers any time I want. Let’s say I want to access number of maps. In any script I have, I would just write:
someValue = Constants.NumberOfMaps;
Why is this useful? Well, you’re gonna store your maximum map size here, as arrays are limited in size, unlike Lists which have only 1 limitation - heap size.
So, your Constants script would look something like this now:
using UnityEngine;
public static class Constants
{
public static ushort maxTilesX = 1000;
public static ushort maxTilesY = 1000;
}
assuming the maximum amount of X and Y tiles is 1000. You can adjust this.
Now, onto the map data. The way you can save your map is by loading the array you have with tile ID numbers. Let’s say:
public enum TileID
{
dirt = 0,
grass = 1,
water = 2,
flowingWater = 3
}
This is just an example, it can go on for quite a bit. I think the only limit is int size, but I doubt you could type in 2^31 - 1 tile types.
Anyways, let’s say you have your map, and you want the 1st row to have 4 adjacent dirt blocks, the 2nd row 2 water blocks, then 2 flowing water, and the 3rd row to have 4 adjacent grass blocks.
You could define the map like this then:
ushort[,] Map = new ushort[Constants.maxTilesX, Constants.maxTilesY];
Map[0, 0] = Map[1, 0] = Map[2, 0] = Map[3, 0] = (ushort)TileID.dirt;
Map[0, 1] = Map[1, 1] = (ushort)TileID.water;
Map[2, 1] = Map[3, 1] = (ushort)TileID.flowingWater;
Map[0, 2] = Map[1, 2] = Map[2, 2] = Map[3, 2] = (ushort)TileID.grass;
Now, the rest is up to you: you would have to create a program which would let you easily add in these blocks - you can either create a function that will save your map after it analyzes game object positions in the editor, or you can create a seperate program which will, outside of unity, create the array for you (which you can then serialize, OR serialize before and write a script in unity to unpack the data). Either way, the idea is to record tile types ideally via enumerators which hold unique values and save them in an array so that when you load the map, Unity can load the whole array, reconstruct the scene for you, and record the adjacent tile ID’s of your player. Then, when attempting to move, you can read the adjacent tile IDs and if they’re on a list of ID’s you can’t walk into, you can play a sound and an in place running animation like in Pokemon, or do nothing.