Unity记录4.3-存储-点击Tilemap保存或读取区块

汇总:Unity 记录

摘要:点击tilemap,文件 保存/读取 该地图区块数据。

思路-2023/08/17

  • 保存和读取上,都很土,都是两层循环,暂时没找到可以批量处理的。
    • 如果大家有更好的方式欢迎留言,我找到更好的方式之后也会在这里更新。
  • 分块:地图被分为若干块,每块大小一样,以避免大地图长时间加载。
  • 存储形式:地图暂时以二维数组保存,二维数组的xy即地图块内的xy,值为tile ID(见上篇Sec. 4.2)。
  • 保存:Tilemap中,tile.name为tile的文件名,因此tilemap保存为ID数组时,需要将tile转name,在从name转ID。
  • 读取:与保存相反,ID需要转为tile,因此一个额外的ID2tileName字典被设计,即ID转name转tile。
  • Tile保存:在读取中,一个10x10的block会循环100次,其中包含诸多重复Tile。在上篇中,Tile通过文件读取。为减少IO操作,Tile文件在被首次读取时,会被记录,因此一个name2tile字典被设计。

数据结构-2023/08/16

public struct TileInfo{
    public string ID;
    public string name;
    public string description;
    public string path;
};

public struct TilesInfo{
    public string version;
    public string date;
    public Dictionary<string, TileInfo> tiles;
}

public struct TilemapInfo{
    public int[] block_offset;
    public List<List<string>> map;
}

private static TilesInfo tilemap_info;
private Dictionary<string, TileBase> name2tile;
private Dictionary<string, string> ID2tileName;
public Vector3Int block_size;

初始化相关-2023/08/16

  • 加载上篇的TilesInfo,即名字转路径,用于从本地读取tile。
void load_tiles_info(){
    // load config
    string tiles_info_path = "Assets/Resources/Saved/TilesInfo.json";
    string jsonText = File.ReadAllText(tiles_info_path);
    tilemap_info = JsonConvert.DeserializeObject<TilesInfo>(jsonText);
    // init
    name2tile = new Dictionary<string, TileBase>();
    ID2tileName = new Dictionary<string, string>();
    // init ID2tileName
    ID2tileName.Add("0", "");
    foreach (var tile_kv in tilemap_info.tiles){
        ID2tileName.Add(tile_kv.Value.ID, tile_kv.Key);
    }
}

转换函数-2023/08/16

  • tile名为空,ID为"0"时表示无tile。
public TileBase map_name_to_tile(string name){
    if (name == ""){
        // No tile
        return null;
    }
    if (name2tile.ContainsKey(name)){
        // Tile have been loaded
        return name2tile[name];
    }
    else{
        // Load tile
        string tile_path = tilemap_info.tiles[name].path;
        TileBase tile = Resources.Load<TileBase>(tile_path);
        name2tile.Add(name, tile);
        return tile;
    }
}

public TileBase map_ID_to_tile(string ID){
    return map_name_to_tile(ID2tileName[ID]);
}

public string map_tile_to_ID(TileBase tile){
    if (tile == null){
        return "0";
    }
    else{
        return tilemap_info.tiles[tile.name].ID;
    }
}

保存与加载-2023/08/17

  • 保存与加载代码的结构类似,
    • 首先生成文件名,得到地图块在tilemap上的位置,
    • 遍历 待保存/待读取 的数据,将地图块中的相对位置转为tilemap中的绝对位置,
    • 将绝对位置上的数据 记录至二维数组/SetTile到tilemap
public void save_tilemap(Tilemap tilemap, int[] block_offsets){
    // file name
    string filename = "Map_" + block_offsets[0] + "-" + block_offsets[1] + ".json";
    string file_path = "Assets/Resources/Saved/" + filename;
    // Get actual position of block
    Vector3Int map_offset = new Vector3Int(block_offsets[0] * block_size[0], block_offsets[1] * block_size[1]);
    // Init tilemap struct
    TilemapInfo tilemap_info = new TilemapInfo {};
    tilemap_info.block_offset = block_offsets;
    tilemap_info.map = new List<List<string>>();
    // Loop for saving
    for (int x = 0; x < block_size[0]; x++){
        List<string> map_row = new List<string>();
        for (int y = 0; y < block_size[1]; y++){
            // Get actual position of tile
            Vector3Int tile_offset = new Vector3Int(map_offset[0] + x, map_offset[1] + y);
            TileBase tile = tilemap.GetTile(tile_offset);
            // Record tile info
            string tile_ID = map_tile_to_ID(tile);
            map_row.Add(tile_ID);
        }
        tilemap_info.map.Add(map_row);
    }
    // save
    string tilemap_info_json = JsonConvert.SerializeObject(tilemap_info, Formatting.Indented);
    File.WriteAllText(file_path, tilemap_info_json);
}

public void load_tilemap(Tilemap tilemap, int[] block_offsets){
    // read file
    string filename = "Map_" + block_offsets[0] + "-" + block_offsets[1] + ".json";
    string file_path = "Assets/Resources/Saved/" + filename;
    if (!File.Exists(file_path)){
        // No data
        return;
    }
    string jsonText = File.ReadAllText(file_path);
    TilemapInfo block_info = JsonConvert.DeserializeObject<TilemapInfo>(jsonText);
    // Get actual position of block
    Vector3Int map_offset = new Vector3Int(block_offsets[0] * block_size[0], block_offsets[1] * block_size[1]);

    // Loop for loading
    for (int x = 0; x < block_size[0]; x++){
        List<string> map_row = new List<string>();
        for (int y = 0; y < block_size[1]; y++){
            // Get actual position of tile
            Vector3Int tile_offset = new Vector3Int(map_offset[0] + x, map_offset[1] + y);
            string tile_ID = block_info.map[x][y];
            // Load tile 
            TileBase tile = map_ID_to_tile(tile_ID);
            tilemap.SetTile(tile_offset, tile);
        }
    }

点击以保存/读取-2023/08/17

  • 和Sec. 3.1的拖动鼠标放置tile的事件一样实现,首先鼠标位置转tilemap坐标,再转block位置,再运行保存函数与读取函数。
  • 效果和想象的一样,挺好
if (input_base.isKeydown("Fire2")){
    Vector3Int pos_tilemap = tilemap_modify.WorldToCell(input_base.get_mouse_pos(1));
    int[] block_offset = {Mathf.Abs(pos_tilemap.x) / tilemap_base.block_size[0], Mathf.Abs(pos_tilemap.y) / tilemap_base.block_size[1]};
    if (pos_tilemap.x < 0){
        block_offset[0] = -block_offset[0] - 1;
    }
    if (pos_tilemap.y < 0){
        block_offset[1] = -block_offset[1] - 1;
    }
    Debug.Log("Mouse pos: [" + pos_tilemap.x + ", " + pos_tilemap.y + "].");
    Debug.Log("Block offset: [" + block_offset[0] + ", " + block_offset[1] + "].");
    tilemap_base.save_tilemap(tilemap_modify, block_offset);
} 
if (input_base.isKeydown("Fire3")){
    Vector3Int pos_tilemap = tilemap_modify.WorldToCell(input_base.get_mouse_pos(1));
    int[] block_offset = {Mathf.Abs(pos_tilemap.x) / tilemap_base.block_size[0], Mathf.Abs(pos_tilemap.y) / tilemap_base.block_size[1]};
    if (pos_tilemap.x < 0){
        block_offset[0] = -block_offset[0] - 1;
    }
    if (pos_tilemap.y < 0){
        block_offset[1] = -block_offset[1] - 1;
    }
    Debug.Log("Mouse pos: [" + pos_tilemap.x + ", " + pos_tilemap.y + "].");
    Debug.Log("Block offset: [" + block_offset[0] + ", " + block_offset[1] + "].");
    tilemap_base.load_tilemap(tilemap_modify, block_offset);
} 

版权声明:
作者:MWHLS
链接:https://mwhls.top/4816.html
来源:无镣之涯
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
< <上一篇
下一篇>>
文章目录
关闭
目 录