This is sort of a DOTS question, although its more of a “I’ve never done this before, how does one solve this problem” question. I have a multiHashMap filled with “TileData”. I can get the data about a specific tile by clicking over the tile, and accessing the information through turning the mouseposition into a hashIndex, and looking up the tileData in the multiHashMap. My issue is I don’t know how to approach being able to “paint” tiles in the editor and save the tiles as an array to be used whenever the map needs to be loaded. Part of the issue is that these tiles are strictly structs of data. They are not entities, and are not rendered on the screen. I tried making each tile an entity with a translation, rotation, localToWorld and renderer component, but I got rather disappointing performance with just 10,000 of these entities.
So I think keeping the TileData strictly as data is probably best. My current idea (which I do not know how to do) is to somehow paint a terrain gameobject with different textures (I don’t know of a better way than a terrain gameobject, but if there is a more tile-friendly collision box generating technique, please, do tell) , hit a “save” button (which will require a custom editor, I can do that much), and the custom editor will look at the terrain object and translate each tile into data (such as resource type, if walkable, if buildable, if has status (and what the status is)). I suppose that if I use this system, then anything that changes the tile data will need to reflect the change graphically on the terrain object (such as a tile filled with lava is now cooled/ drained).
For reference this is a top down, perspective RTS like StarCraft, WarCraft, They are Billions, and Star Wars: Empire at War. I’m not using tiles in a heavy simulation fashion like in Oxygen Not Included, or Barotrauma.
currently I have a terrain object 100 by 100 units wide, and I set in code the number of tiles in the map (10 tiles a unit, for 10,000 tiles). The type of tile I set is just a default tile as a placeholder until I get a more precise way of calculate tile locations. Here is my relevant code to the tilesystem.
//this is in the GameSceneManager class
public MapData mapSpawnData;
private void Awake()
{
mapSpawnData = new MapData
{
length = 10,
width = 10,
bottomLeftCornerOrigin=new float3(0,0,0),
tiles= new TileData[10000]
};
//This is in the QuadrantSystem class. This is where all my tile
//code is. It is called the quadrant system because I also have
//the map broken into quadrants. The stated map size above is
//in quadrants, not tiles. Quadrants help localize unit targeting.
//There are 10x10 tiles in a quad.
public static NativeMultiHashMap<int, MapQuadData> quadrentMultiHashMap;
public static NativeMultiHashMap<int, TileData> tileMulitHashMap;
public const int mapQuadrentCellSize = 10;
public const int mapQuadrantZMultiplier = 1000;
public const int tileQuadrantCellSize = 1;
public const int tileQuadrantZMultiplier = 10000;
protected override void OnCreate()
{
quadrentMultiHashMap = new NativeMultiHashMap<int, MapQuadData>(0, Allocator.Persistent);
tileMulitHashMap = new NativeMultiHashMap<int, TileData>(0, Allocator.Persistent);
base.OnCreate();
}
MapData map = GameSceneManager.instance.mapSpawnData;
int length = map.tiles.Length;
tileMulitHashMap.Capacity = length;
TileData defaultTile = new TileData
{
walkable = true,
height = new float2(0, 0),
position = new float2(0, 0),
buildable = true,
structureBuiltOn = false,
resource = 0,
//status = new int[0] Since status is an int array, I
//couldn't put it in a struct. I may just assing status1 2 and 3,
//because I doubt that more than 3 status can be on a tile at
//once. I currently have no plans to implement status, I just
//want the option to be open should I decide at a later date to
//encompass them.
};
for (int i = 0; i < length; i++)
{
int hashMapKey = GetTilePositionHashMapKey(new float3(i%(map.length*10),0,math.floor(i/(map.width*10)))); //(tileQuadrantCellSize * i) + math.floor((i / (map.width * 10)))
// tileMulitHashMap.Add(hashMapKey, map.tiles[i]);
//This is how I would like to assign the tileData, but since the
//map is currently generated at runtime, and not from a
//predefined tile array, I need to use newTile.
TileData newTile = defaultTile;
newTile.position = new float2(i % (map.length * 10), math.floor(i / (map.width * 10)));
tileMulitHashMap.Add(hashMapKey, newTile);
}
}
protected override void OnDestroy()
{
tileMulitHashMap.Dispose();
quadrentMultiHashMap.Dispose();
base.OnDestroy();
}
private static int GetTilePositionHashMapKey(float3 position)
{
return (int)(math.floor(position.x / tileQuadrantCellSize) + (tileQuadrantZMultiplier * math.floor(position.z / tileQuadrantCellSize)));
}
Any help is appreciated. If someone thinks that this thread is too far off from DOTS and should be posted elsewhere, please say so.