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

255 lines
11 KiB
C#
Raw Normal View History

// Managers/TileManager.cs
using System;
using Data;
using Utils;
2025-08-28 16:20:24 +08:00
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;
}
2025-08-28 16:20:24 +08:00
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(); // 清空地图生成器工作类映射
}
2025-08-28 16:20:24 +08:00
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);
}
}
}