using UnityEngine; using UnityEngine.Tilemaps; using Newtonsoft.Json; using System; using System.Threading.Tasks; using Managers; using Utils; namespace Map { public enum MapDimension { Base = 0, // 对应 Landform.baseTilemap Building = 1, // 对应 Landform.buildingTilemap Plant = 2 // 对应 Landform.plantTilemap } public class BasicTerrainGeneratorConfig { [JsonProperty("tileDefName", Required = Required.Always)] public string TileDefName { get; set; } = "DefaultTerrainTile"; // 瓦片的定义名称 // 将 Threshold 改为 MinThreshold,并保持旧的JsonProperty名称以兼容旧JSON [JsonProperty("threshold")] public double MinThreshold { get; set; } // 柏林噪声的最小阈值。-1到1之间。将其默认值改为0.0以适应-1到1的噪声范围,并提供更灵活的区间开始。 [JsonProperty("maxThreshold")] public double MaxThreshold { get; set; } = 1.0; // 柏林噪声的最大阈值。-1到1之间。默认为1.0以兼容旧配置。 [JsonProperty("elseTileDefName")] public string ElseTileDefName { get; set; } // 不满足Min/MaxThreshold范围时放置的瓦片定义名称,默认为null表示不放置。 [JsonProperty("scale")] public double Scale { get; set; } = 0.1; // 柏林噪声的缩放因子,控制地形特征的大小 [JsonProperty("offsetX")] public double OffsetX { get; set; } // 柏林噪声的X轴偏移 [JsonProperty("offsetY")] public double OffsetY { get; set; } // 柏林噪声的Y轴偏移 [JsonProperty("mapCellSizeX")] public int MapCellSizeX { get; set; } = 100; // 地图生成区域的宽度(单元格数量) [JsonProperty("mapCellSizeY")] public int MapCellSizeY { get; set; } = 100; // 地图生成区域的高度(单元格数量) [JsonProperty("targetDimension")] public MapDimension TargetDimension { get; set; } = MapDimension.Base; // 新增:地图生成区域的起始X坐标(单元格数量) [JsonProperty("originX")] public int OriginX { get; set; } // 新增:地图生成区域的起始Y坐标(单元格数量) [JsonProperty("originY")] public int OriginY { get; set; } } // MapDimension 枚举在此文件中不重复定义,因为它通常位于自己的文件中或 Map 命名空间的其他通用文件中。 // 如果它与 BasicTerrainGeneratorConfig 在同一个文件,则在 BasicTerrainGeneratorConfig 定义后。 public class BasicTerrainMapGenerator : MapGeneratorWorkClassBase { private BasicTerrainGeneratorConfig _config; /// /// 初始化地形生成器,解析JSON配置字符串。 /// /// 包含地形生成参数的JSON字符串。 public override void Init(string value) { try { _config = JsonConvert.DeserializeObject(value); // _config 不是单例,所以需要进行空检查。 if (_config == null) { Debug.LogError("基本地形生成器: 配置反序列化为空。请检查JSON格式。"); _config = new BasicTerrainGeneratorConfig(); } if (string.IsNullOrWhiteSpace(_config.TileDefName)) { Debug.LogWarning("基本地形生成器: 瓦片定义名称为空。使用默认值 'DefaultTerrainTile'。"); _config.TileDefName = "DefaultTerrainTile"; } if (_config.Scale <= 0) { Debug.LogWarning($"基本地形生成器: 缩放值必须为正。设置为默认值 0.1。当前值: {_config.Scale}"); _config.Scale = 0.1; } if (_config.MapCellSizeX <= 0 || _config.MapCellSizeY <= 0) { Debug.LogWarning( $"基本地形生成器: 地图单元格宽度或高度为零或负数。设置为默认值 (100, 100)。当前值: ({_config.MapCellSizeX}, {_config.MapCellSizeY})"); _config.MapCellSizeX = 100; _config.MapCellSizeY = 100; } // 将阈值限定在 -1.0 到 1.0 的有效范围内 _config.MinThreshold = Math.Max(-1.0, Math.Min(1.0, _config.MinThreshold)); _config.MaxThreshold = Math.Max(-1.0, Math.Min(1.0, _config.MaxThreshold)); // 确保 MinThreshold 不大于 MaxThreshold if (_config.MinThreshold > _config.MaxThreshold) { Debug.LogWarning( $"基本地形生成器: 最小阈值 ({_config.MinThreshold}) 不能大于最大阈值 ({_config.MaxThreshold})。交换值。"); (_config.MinThreshold, _config.MaxThreshold) = (_config.MaxThreshold, _config.MinThreshold); // 交换值 } } catch (JsonSerializationException ex) { Debug.LogError($"基本地形生成器: JSON反序列化错误: {ex.Message}。输入: {value}"); _config = new BasicTerrainGeneratorConfig(); // 失败时使用默认配置 } catch (Exception ex) { Debug.LogError($"基本地形生成器: Init 期间发生意外错误: {ex.Message}。输入: {value}"); _config = new BasicTerrainGeneratorConfig(); // 失败时使用默认配置 } } /// /// 根据柏林噪声生成地形。此方法现在是异步的,以避免阻塞主线程。 /// /// 地图生成器实例,包含要操作的瓦片地图。 public override async Task Process(Landform landform) { // _config 不是单例,所以需要进行空检查。 if (_config == null) { Debug.LogError("基本地形生成器: Process 在 Init 之前调用或 Init 失败。使用默认配置。"); _config = new BasicTerrainGeneratorConfig(); } var terrainTile = TileManager.Instance.GetTile(_config.TileDefName); if (terrainTile == null) { Debug.LogError($"基本地形生成器: 无法获取瓦片定义名称: '{_config.TileDefName}'。中止生成。"); return; } TileBase elseTile = null; if (!string.IsNullOrWhiteSpace(_config.ElseTileDefName)) { elseTile = TileManager.Instance.GetTile(_config.ElseTileDefName); if (elseTile == null) { Debug.LogWarning($"基本地形生成器: 无法获取 else-瓦片定义名称: '{_config.ElseTileDefName}'。将不会放置 else-瓦片。"); } } Tilemap targetTilemap; switch (_config.TargetDimension) // 直接对枚举值进行 switch { case MapDimension.Base: targetTilemap = landform.baseTilemap; break; case MapDimension.Building: targetTilemap = landform.buildingTilemap; break; case MapDimension.Plant: targetTilemap = landform.plantTilemap; break; default: // 理论上不会走到这里,因为 TargetDimension 是枚举类型,但以防万一 Debug.LogWarning( $"基本地形生成器: 收到未知的目标维度枚举值 '{_config.TargetDimension}'。将使用默认的 'Base' 瓦片地图。"); targetTilemap = landform.baseTilemap; break; } if (targetTilemap == null) { Debug.LogError( $"基本地形生成器: 选定的 Tilemap ({_config.TargetDimension}) 为 null。请确保 Landform 对象上已正确分配 Tilemap。中止生成。"); return; } for (var x = 0; x < _config.MapCellSizeX; x++) { for (var y = 0; y < _config.MapCellSizeY; y++) { var sampleX = x / (double)_config.MapCellSizeX * _config.Scale + _config.OffsetX; var sampleY = y / (double)_config.MapCellSizeY * _config.Scale + _config.OffsetY; var noiseValue = PerlinNoise.Instance.Noise(sampleX, sampleY); // 核心修改部分:将 x, y 与 OriginX, OriginY 相加,用于指定瓦片的实际放置位置。 Vector3Int tilePosition = new Vector3Int(x + _config.OriginX, y + _config.OriginY, 0); if (noiseValue >= _config.MinThreshold && noiseValue <= _config.MaxThreshold) { targetTilemap.SetTile(tilePosition, terrainTile); } else if (elseTile != null) { targetTilemap.SetTile(tilePosition, elseTile); } else { targetTilemap.SetTile(tilePosition, null); } } await Task.Yield(); } } /// /// 获取当前配置的地图尺寸。 /// /// 表示地图宽度和高度的 Vector2Int。 public override Vector2Int GetSize() { // _config 不是单例,所以需要进行空检查。 if (_config == null) { Debug.LogError("BasicTerrainMapGenerator: GetSize 在 Init 之前调用或 Init 失败。返回默认尺寸 (0,0)。"); return Vector2Int.zero; } // 返回的是生成区域的尺寸,而不是它的起始位置。 return new Vector2Int(_config.MapCellSizeX, _config.MapCellSizeY); } } }