using System.Collections.Generic; using System.Threading.Tasks; using Managers; using Newtonsoft.Json; using UnityEngine; using UnityEngine.Tilemaps; namespace Map { public class ConditionalTileGeneratorConfig { // ====== 生成瓦片配置 ====== [JsonProperty("outputTileDefName", Required = Required.Always)] public string OutputTileDefName { get; set; } [JsonProperty("outputLayer", Required = Required.Always)] public string OutputLayer { get; set; } // "base", "building", "plant" // ====== 条件检查配置 ====== [JsonProperty("conditionTileDefNames")] // 属性名改为复数形式 public List ConditionTileDefNames { get; set; } = null; // 如果非空,则只有在目标层有此瓦片列表中的任意一个时才生成 [JsonProperty("conditionLayer")] public string ConditionLayer { get; set; } = null; // 检查条件瓦片的层 // ====== 区域配置 ====== [JsonProperty("positionX", Required = Required.Always)] public int PositionX { get; set; } = 0; // 起始位置X [JsonProperty("positionY", Required = Required.Always)] public int PositionY { get; set; } = 0; // 起始位置Y [JsonProperty("width", Required = Required.Always)] public int Width { get; set; } = 1; // 区域宽度 [JsonProperty("height", Required = Required.Always)] public int Height { get; set; } = 1; // 区域高度 // ====== 柏林噪声配置 ====== [JsonProperty("usePerlinNoise")] public bool UsePerlinNoise { get; set; } = false; [JsonProperty("perlinScale")] public float PerlinScale { get; set; } = 10f; // 柏林噪声频率,数值越大越粗糙 [JsonProperty("perlinThreshold")] public float PerlinThreshold { get; set; } = 0.5f; // 柏林噪声阈值,只有噪声值高于此值才生成瓦片 [JsonProperty("perlinOffsetX")] public float PerlinOffsetX { get; set; } = 0f; // 柏林噪声X偏移 [JsonProperty("perlinOffsetY")] public float PerlinOffsetY { get; set; } = 0f; // 柏林噪声Y偏移 } public class ConditionalTileGenerator : MapGeneratorWorkClassBase { private ConditionalTileGeneratorConfig _config; private TileBase _outputTileBase; // 缓存要生成的实际 TileBase 资源 private HashSet _conditionTileBaseNames; // 缓存条件瓦片的运行时名称集合 /// /// 初始化条件瓦片生成器,解析JSON配置并预加载资源。 /// /// 包含ConditionalTileGeneratorConfig的JSON字符串。 public override void Init(string value) { if (string.IsNullOrEmpty(value)) { Debug.LogError("ConditionalTileGenerator: Init received empty or null JSON value."); return; } try { _config = JsonConvert.DeserializeObject(value); if (_config == null) { Debug.LogError( "ConditionalTileGenerator: Failed to deserialize ConditionalTileGeneratorConfig from JSON."); return; } // 预加载输出瓦片 if (!string.IsNullOrEmpty(_config.OutputTileDefName)) { _outputTileBase = TileManager.Instance.GetTile(_config.OutputTileDefName); if (_outputTileBase == null) { Debug.LogWarning( $"ConditionalTileGenerator: Output tile asset for '{_config.OutputTileDefName}' not found via TileManager. Generation may fail."); } } else { Debug.LogError( "ConditionalTileGenerator: OutputTileDefName is required but not provided in config."); return; } // 预加载条件瓦片的名称集合 (如果指定) if (_config.ConditionTileDefNames != null && _config.ConditionTileDefNames.Count > 0) { _conditionTileBaseNames = new HashSet(); foreach (var defName in _config.ConditionTileDefNames) { if (string.IsNullOrEmpty(defName)) { Debug.LogWarning("ConditionalTileGenerator: Found empty or null condition tile definition name in config. Skipping."); continue; } var conditionAsset = TileManager.Instance.GetTile(defName); if (conditionAsset != null) { _conditionTileBaseNames.Add(conditionAsset.name); } else { Debug.LogWarning( $"ConditionalTileGenerator: Condition tile asset for '{defName}' not found via TileManager. This specific condition tile will be ignored in checks."); } } // 如果最终没有有效条件瓦片被加载,则将HashSet设为null,表示不进行此条件检查 if (_conditionTileBaseNames.Count == 0) { _conditionTileBaseNames = null; } } else { // 如果配置中未指定条件瓦片列表,或者列表为空,显式设置为null以表示无需检查此条件 _conditionTileBaseNames = null; } } catch (JsonException ex) { Debug.LogError($"ConditionalTileGenerator: JSON deserialization error: {ex.Message}\nJSON: {value}"); } } /// /// 获取条件瓦片生成器将影响的区域大小。 /// /// 表示区域宽和高的Vector2Int。 public override Vector2Int GetSize() { if (_config == null) { return Vector2Int.zero; } return new Vector2Int(_config.Width, _config.Height); } /// /// 执行条件瓦片生成逻辑。 /// /// MapGenerator实例,提供Tilemap和坐标转换功能。 public override async Task Process(Landform landform) { if (_config == null || _outputTileBase == null) { Debug.LogError("ConditionalTileGenerator: Configuration or output tile not properly initialized."); return; } if (landform == null || landform.baseTilemap == null || landform.buildingTilemap == null || landform.plantTilemap == null) { Debug.LogError("ConditionalTileGenerator: MapGenerator or its Tilemaps are not assigned."); return; } // 获取输出层 Tilemap var outputTilemap = GetTilemapByName(landform, _config.OutputLayer); if (outputTilemap == null) { Debug.LogError( $"ConditionalTileGenerator: Output Tilemap '{_config.OutputLayer}' not found or invalid."); return; } // 获取条件层 Tilemap (如果需要检查条件瓦片) Tilemap conditionTilemap = null; // 只有当有实际的条件瓦片名称列表配置时才尝试获取条件层Tilemap bool hasConditionTileNamesConfigured = (_conditionTileBaseNames != null && _conditionTileBaseNames.Count > 0); if (hasConditionTileNamesConfigured) { if (string.IsNullOrEmpty(_config.ConditionLayer)) { Debug.LogWarning( "ConditionalTileGenerator: 'ConditionTileDefNames' specified, but 'ConditionLayer' is not. Condition check related to specific tiles will implicitly fail for the tile conditions."); // 此时不设置 conditionTilemap,会在循环内部触发 conditionsMet = false } else { conditionTilemap = GetTilemapByName(landform, _config.ConditionLayer); if (conditionTilemap == null) { Debug.LogError( $"ConditionalTileGenerator: Condition Tilemap '{_config.ConditionLayer}' not found or invalid. Condition check related to specific tiles will implicitly fail for the tile conditions."); // 此时不设置 conditionTilemap,会在循环内部触发 conditionsMet = false } } } for (var y = 0; y < _config.Height; y++) { for (var x = 0; x < _config.Width; x++) { var currentGridPos = new Vector3Int(_config.PositionX + x, _config.PositionY + y, 0); var conditionsMet = true; // 1. 检查条件瓦片 (仅当有有效的条件瓦片和条件层Tilemap时执行) if (conditionsMet && hasConditionTileNamesConfigured) // 只有配置了条件瓦片才进行进一步检查 { if (conditionTilemap != null) // 确保条件层Tilemap有效 { var tileOnConditionLayer = conditionTilemap.GetTile(currentGridPos); // 如果当前位置没有瓦片,或者瓦片名称不在允许的条件列表中,则条件不满足 if (tileOnConditionLayer == null || !_conditionTileBaseNames.Contains(tileOnConditionLayer.name)) { conditionsMet = false; // 条件不满足 // Debug.Log($"Skipping {currentGridPos}: Condition tile not found or not in allowed list."); } } else { // 如果 hasConditionTileNamesConfigured 为 true, 但 conditionTilemap 为 null (因为_config.ConditionLayer为空或GetTilemapByName失败) // 那么条件瓦片检查无法进行,应该视为条件不满足 conditionsMet = false; } } // 2. 检查柏林噪声 if (conditionsMet && _config.UsePerlinNoise) { var sampleX = (currentGridPos.x + _config.PerlinOffsetX) / _config.PerlinScale; var sampleY = (currentGridPos.y + _config.PerlinOffsetY) / _config.PerlinScale; var perlinValue = Mathf.PerlinNoise(sampleX, sampleY); if (perlinValue < _config.PerlinThreshold) { conditionsMet = false; // 噪声条件不满足 // Debug.Log($"Skipping {currentGridPos}: Perlin noise {perlinValue:F2} below threshold {_config.PerlinThreshold:F2}."); } } // 如果所有条件都满足,则放置瓦片 if (conditionsMet) { outputTilemap.SetTile(currentGridPos, _outputTileBase); // Debug.Log($"ConditionalTileGenerator: Placed '{_config.OutputTileDefName}' at {currentGridPos}."); } } await Task.Yield(); // 允许在每行结束时暂停,避免阻塞 } } /// /// 根据名称字符串获取 MapGenerator 中的对应 Tilemap。 /// private Tilemap GetTilemapByName(Landform landform, string tilemapName) { switch (tilemapName?.ToLower()) // 使用ToLower以便不区分大小写 { case "base": return landform.baseTilemap; case "building": return landform.buildingTilemap; case "plant": return landform.plantTilemap; default: Debug.LogWarning($"ConditionalTileGenerator: Unknown Tilemap name '{tilemapName}'."); return null; } } } }