Unity记录4.1-存储-根据关键字加载Tile(2023/09/30更新)
汇总:Unity 记录
摘要:实现完 Tilemap 地图生成后,实现根据关键字加载Tile。
2023/09/30更新:更新了addressable加载tile的可行方式。
- 保存地图首先要能根据关键字来加载地图,而不是在inspector里面拖拖拖,所以首先是根据路径加载本地文件。
Addressable Assets System(没成功)-2023/08/13-2023/08/14
- 使用 Addressable Assets System 来进行动态地图加载。
- 相关资源:
- 但是我试了很多方式,没办法实现加载tilebase,然后在tilemap上绘制。
- 下面的代码可以正确加载prefab,执行之后会有一堆prefab在inspector上,但绘制tilemap会报错。
- 使用tilemap绘制tile时并不会改变inspector的内容,主要问题应该是
GameObject tilePrefab = handle.Result;
只能使用GameObject
,不能使用TileBase
。
async void place_tiles(Tilemap tilemap, ArrayList pos_array){
AsyncOperationHandle<GameObject> handle = Addressables.LoadAssetAsync<GameObject>("Assets/ResourcesAddressable/Prefab/Block/SoilBlock.prefab");
await handle.Task;
GameObject tilePrefab = handle.Result;
GameObject instantiatedTile = Instantiate(tilePrefab);
TileBase tile = instantiatedTile.GetComponent<TileBase>();
foreach (Vector3Int pos in pos_array){
tilemap.SetTile(pos, tile);
}
}
Resources加载-2023/08/14
- 这个实际上是我五个月前的方案,
- 但是因为现在有GPT可以问了,它给我推荐了Addressable,看起来也确实不错,所以先写的上面的方案。
- 如下面代码所示,我加载的是asset,而不是prefab,只用两行就实现了。
- 实际路径是"Assets\Resources\Tilemap\Block\Soil/1_GrassSoilBlock.asset",省略Resources及其前缀,省略文件扩展名。
- 使用addressable加载,不论是asset还是prefab,它都返回的是
GameObject
类型,我找不到转为TileBase
的方案。
string tile_path = "Tilemap/Block/Soil/1_GrassSoilBlock";
TileBase tile = Resources.Load<TileBase>(tile_path);
Addressable 加载 tile-2023/09/30
- 已加载成功,流程如下。
- 加载仅在下面的第3 7 8 9行。
action_tile_loaded()
这个函数实际上并不被调用。- 这个函数能正常运行,它在其生命周期内也能修改
__name2tile
,然而,在结束对所有tile的load_tile()
调用后,__name2tile
就会恢复成空字典。 - 同时,在我使用类似的代码,加载prefab时,一切正常。
async UniTaskVoid load_tile(string name){
string object_path = __tiles_info.tiles[name].path;
AsyncOperationHandle<TileBase> handle = Addressables.LoadAssetAsync<TileBase>(object_path);
if (name == "") // that is false.
handle.Completed += action_tile_loaded;
else{
handle.WaitForCompletion();
__name2tile.Add(handle.Result.name, handle.Result);
Addressables.Release(handle);
}
await UniTask.Yield();
}
void load_tiles_info(){
// load config
string tiles_info_path = __game_configs.__tilesInfo_path;
string jsonText = File.ReadAllText(tiles_info_path);
__tiles_info = JsonConvert.DeserializeObject<TilesInfo>(jsonText);
// init ID2tileName
__ID2tileName.Add(0, "");
foreach (var tile_kv in __tiles_info.tiles){
__ID2tileName.Add(tile_kv.Value.ID, tile_kv.Key);
load_tile(tile_kv.Key).Forget();
}
}
void action_tile_loaded(AsyncOperationHandle<TileBase> handle){
if (handle.Status == AsyncOperationStatus.Succeeded) __name2tile.Add(handle.Result.name, handle.Result);
else Debug.LogError("Failed to load tile: " + handle.DebugName);
Addressables.Release(handle);
}
- 下面是加载预制体的方法,
- 可以看到,上面
load_tile()
的4到10行,只有第5行被留下,简略成了下面load_object()
的第4行。 - 其它地方,除了类型与名称,无任何变化。
- 而下面能够正常修改查询字典,上面不行,所以上面用了一个
if else
,只使用else
的部分来修改查询字典。
- 可以看到,上面
async UniTaskVoid load_object(string name){
string object_path = _objects_info.objects[name].path;
AsyncOperationHandle<GameObject> handle = Addressables.LoadAssetAsync<GameObject>(object_path);
handle.Completed += action_prefab_loaded;
await UniTask.Yield();
}
void load_objects(){
string objects_info_path = _game_configs.__objectsInfo_path;
string jsonText = File.ReadAllText(objects_info_path);
_objects_info = JsonConvert.DeserializeObject<ObjectsInfo>(jsonText);
_ID2objectName.Add("0", "");
foreach (var object_kv in _objects_info.objects){
_ID2objectName.Add(object_kv.Value.ID, object_kv.Key);
load_object(object_kv.Key).Forget();
}
}
void action_prefab_loaded(AsyncOperationHandle<GameObject> handle){
if (handle.Status == AsyncOperationStatus.Succeeded) _name2object.Add(handle.Result.name, handle.Result);
else Debug.LogError("Failed to load prefab: " + handle.DebugName);
Addressables.Release(handle);
}
文章目录
关闭
共有 0 条评论