Files
Gen_Hack-and-Slash-Roguelite/Client/Assets/Scripts/Managers/TileManager.cs

255 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Managers/TileManager.cs
using System;
using Data;
using Utils;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Map;
using UnityEngine;
using UnityEngine.Tilemaps;
using Object = UnityEngine.Object;
namespace Managers
{
public class TileManager : Singleton<TileManager>, ILaunchManager
{
public string StepDescription => "正在加载瓦片";
// 缓存所有根据定义生成的RuleTile实例
private Dictionary<string, RuleTile> _cachedTiles = new();
// 地图生成器工作类映射Key: MapGeneratorDef.defName, Value: MapGeneratorWorkClassBase
private Dictionary<string, MapGeneratorWorkClassBase> _mapGeneratorWorkClassMap = new();
public void Init()
{
// 如果已缓存瓦片,则直接返回
if (_cachedTiles.Any())
return;
var tileDefs = DefineManager.Instance.QueryDefinesByType<TileDef>();
foreach (var def in tileDefs)
{
if (string.IsNullOrEmpty(def.defName))
{
Debug.LogWarning($"发现未定义名称或defName的TileDef已跳过。");
continue;
}
var tileName = def.defName;
var ruleTile = ScriptableObject.CreateInstance<RuleTile>();
ruleTile.name = tileName; // 设置ScriptableObject的名称
ruleTile.m_DefaultColliderType = def.collider;
ruleTile.m_DefaultSprite = PackagesImageManager.Instance.GetSprite(def.texture);
ruleTile.m_TilingRules = GetTileRules(def.rules);
_cachedTiles[tileName] = ruleTile;
}
var generatorDefs = DefineManager.Instance.QueryDefinesByType<MapGeneratorDef>();
foreach (var mapGeneratorDef in generatorDefs)
{
var workClass = StringUtils.CreateMapGeneratorInstance(mapGeneratorDef.workClass);
if (workClass == null)
{
Debug.LogWarning($"无法为地图生成器 '{mapGeneratorDef.defName}' 创建工作类 '{mapGeneratorDef.workClass}',已跳过。");
continue;
}
workClass.Init(mapGeneratorDef.value);
_mapGeneratorWorkClassMap[mapGeneratorDef.defName] = workClass;
}
}
public void Clear()
{
foreach (var tile in _cachedTiles.Values)
{
if (tile != null)
{
Object.Destroy(tile);
}
}
_cachedTiles.Clear();
_mapGeneratorWorkClassMap.Clear(); // 清空地图生成器工作类映射
}
private static List<RuleTile.TilingRule> GetTileRules(RuleTileRuleDef[] rules)
{
return rules?.Select(GetTileRule).ToList();
}
/// <summary>
/// 将自定义的 RuleTileRuleDef 转换为 Unity 的 RuleTile.TilingRule。
/// </summary>
/// <param name="ruleDef">自定义的 RuleTileRuleDef 规则定义。</param>
/// <returns>转换后的 RuleTile.TilingRule 实例。</returns>
private static RuleTile.TilingRule GetTileRule(RuleTileRuleDef ruleDef)
{
if (ruleDef == null)
return null;
var tilingRule = new RuleTile.TilingRule
{
m_Sprites = PackagesImageManager.Instance.GetSprites(ruleDef.animationTextures.ToArray()),
m_Output = ruleDef.outputType,
m_ColliderType = ruleDef.outputCollider,
m_PerlinScale = ruleDef.chance,
m_MaxAnimationSpeed = ruleDef.animationSpeed,
m_MinAnimationSpeed = ruleDef.animationSpeed,
m_RuleTransform = ruleDef.transform
};
// 使用 Dictionary 存储邻居条件,键为位置,值为邻居类型
var neighborConditionsMap = new Dictionary<Vector3Int, int>();
// 预设的8个邻居位置
var defaultPositions = new Vector3Int[]
{
new Vector3Int(-1, 1, 0),
new Vector3Int(0, 1, 0),
new Vector3Int(1, 1, 0),
new Vector3Int(-1, 0, 0),
new Vector3Int(1, 0, 0),
new Vector3Int(-1, -1, 0),
new Vector3Int(0, -1, 0),
new Vector3Int(1, -1, 0)
};
// 处理标准8个邻居条件
for (var i = 0; i < ruleDef.neighborConditions.Length && i < 8; i++)
{
int neighborType;
switch (ruleDef.neighborConditions[i])
{
case RuleTileRuleDef.NeighborConditionType.NotThis:
neighborType = RuleTile.TilingRuleOutput.Neighbor.NotThis;
neighborConditionsMap[defaultPositions[i]] = neighborType; // 添加或更新
break;
case RuleTileRuleDef.NeighborConditionType.This:
neighborType = RuleTile.TilingRuleOutput.Neighbor.This;
neighborConditionsMap[defaultPositions[i]] = neighborType; // 添加或更新
break;
case RuleTileRuleDef.NeighborConditionType.Any:
default:
// 如果是Any或默认则不添加到map中表示不关心此位置
break;
}
}
// 处理扩展邻居条件如果位置重复则覆盖标准8个邻居的定义
if (ruleDef.neighborConditionExtend != null)
{
foreach (var neighborConditionDef in ruleDef.neighborConditionExtend)
{
var pos = Utils.StringUtils.StringToVector3Int(neighborConditionDef.position);
int neighborType;
switch (neighborConditionDef.Type)
{
case RuleTileRuleDef.NeighborConditionType.NotThis:
neighborType = RuleTile.TilingRuleOutput.Neighbor.NotThis;
neighborConditionsMap[pos] = neighborType; // 添加或覆盖
break;
case RuleTileRuleDef.NeighborConditionType.This:
neighborType = RuleTile.TilingRuleOutput.Neighbor.This;
neighborConditionsMap[pos] = neighborType; // 添加或覆盖
break;
case RuleTileRuleDef.NeighborConditionType.Any:
default:
// 如果是Any或默认则不添加到map中
// 如果这个位置之前有定义来自defaultPositions那么Any会有效地“移除”这个定义
// 如果我们希望Any清除之前的显式定义可以在这里neighborConditionsMap.Remove(pos);
// 但通常Any意味着不关心所以保持不添加即可
break;
}
}
}
tilingRule.m_NeighborPositions = new List<Vector3Int>(neighborConditionsMap.Keys);
tilingRule.m_Neighbors = new List<int>(neighborConditionsMap.Values);
return tilingRule;
}
/// <summary>
/// 根据名称获取一个 RuleTile 实例。
/// </summary>
/// <param name="tileName">瓦片的名称 (TileDef.defName)</param>
/// <returns>对应的 RuleTile 实例,如果找不到则返回 null。</returns>
public TileBase GetTile(string tileName)
{
if (_cachedTiles.TryGetValue(tileName, out var tile))
{
return tile;
}
Debug.LogWarning($"瓦片 '{tileName}' 未在TileManager缓存中找到。");
return null;
}
/// <summary>
/// 应用指定的地图生成器,现在是非阻塞的异步操作。
/// </summary>
/// <param name="generatorName">要应用的生成器名称。</param>
/// <param name="landform">可选:指定要使用的 MapGenerator 实例。如果为 null将尝试从 Program.Instance.FocusedDimension 获取。</param>
/// <returns>一个表示异步操作完成的 Task。</returns>
public async Task ApplyMapGenerator(string generatorName, Map.Landform landform = null)
{
if (landform == null)
{
// 尝试从 Program.Instance.FocusedDimension 获取 mapGenerator
// 假设 Program 和 FocusedDimension 结构存在
landform = Program.Instance?.FocusedDimension?.landform;
if (landform == null)
{
Debug.LogError(
$"ApplyMapGenerator: 无法找到地图生成器 '{generatorName}' 对应的 mapGenerator。Program.Instance、FocusedDimension 或其 mapGenerator 可能为空。");
return; // async Task 方法直接 return; 意味着返回 Task.CompletedTask
}
}
if (_mapGeneratorWorkClassMap == null)
{
Debug.LogError($"ApplyMapGenerator: _mapGeneratorWorkClassMap 未初始化,无法找到生成器 '{generatorName}'。");
return;
}
if (_mapGeneratorWorkClassMap.TryGetValue(generatorName, out var mapGeneratorWorkClass))
{
if (mapGeneratorWorkClass == null)
{
Debug.LogError(
$"ApplyMapGenerator: 为生成器 '{generatorName}' 找到了一个空的 IMapGeneratorWorkClass 实例。这表明 _mapGeneratorWorkClassMap 配置存在问题。");
return;
}
try
{
await mapGeneratorWorkClass.Process(landform); // <-- 使用 await 调用异步 Process 方法
}
catch (Exception ex)
{
Debug.LogError($"ApplyMapGenerator: 地图生成器 '{generatorName}' 异步处理过程中发生错误: {ex.Message}");
// 可以在这里根据需要决定是否重新抛出异常
throw; // 抛出异常以通知调用者,或者根据实际情况选择捕获并完全处理
}
}
else
{
Debug.LogError(
$"ApplyMapGenerator: 未找到名为 '{generatorName}' 的 IMapGeneratorWorkClass。请确保该生成器已在 _mapGeneratorWorkClassMap 中注册。");
}
}
public MapGeneratorWorkClassBase GetMapGeneratorWorkClass(string defName)
{
return _mapGeneratorWorkClassMap?.GetValueOrDefault(defName,null);
}
}
}