using UnityEngine; using UnityEngine.Tilemaps; using Newtonsoft.Json; using System; using System.Threading.Tasks; // 引入 System.Threading.Tasks using Managers; using Utils; namespace Map { 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; } = 0.0; // 柏林噪声的最小阈值。0到1之间。将其默认值改为0.0以适应-1到1的噪声范围,并提供更灵活的区间开始。 [JsonProperty("maxThreshold")] public double MaxThreshold { get; set; } = 1.0; // 柏林噪声的最大阈值。0到1之间。默认为1.0以兼容旧配置。 [JsonProperty("elseTileDefName")] public string ElseTileDefName { get; set; } = null; // 不满足Min/MaxThreshold范围时放置的瓦片定义名称,默认为null表示不放置。 [JsonProperty("scale")] public double Scale { get; set; } = 0.1; // 柏林噪声的缩放因子,控制地形特征的大小 [JsonProperty("offsetX")] public double OffsetX { get; set; } = 0.0; // 柏林噪声的X轴偏移 [JsonProperty("offsetY")] public double OffsetY { get; set; } = 0.0; // 柏林噪声的Y轴偏移 [JsonProperty("mapCellSizeX")] public int MapCellSizeX { get; set; } = 100; // 地图生成区域的宽度(单元格数量) [JsonProperty("mapCellSizeY")] public int MapCellSizeY { get; set; } = 100; // 地图生成区域的高度(单元格数量) } // BasicTerrainGeneratorConfig 应该在同一个文件或者它自己的文件中定义, // 这里为了清晰展示修改,假定它在 Map 命名空间下可用。 public class BasicTerrainMapGenerator : MapGeneratorWorkClassBase { private BasicTerrainGeneratorConfig _config; /// /// 初始化地形生成器,解析JSON配置字符串。 /// /// 包含地形生成参数的JSON字符串。 public override void Init(string value) { try { _config = JsonConvert.DeserializeObject(value); // 参数有效性检查 if (_config == null) { Debug.LogError("BasicTerrainMapGenerator: Configuration deserialized to null. Check JSON format."); _config = new BasicTerrainGeneratorConfig(); // 提供默认配置以防崩溃 } if (string.IsNullOrWhiteSpace(_config.TileDefName)) { Debug.LogWarning( "BasicTerrainMapGenerator: TileDefName is empty. Using default 'DefaultTerrainTile'."); _config.TileDefName = "DefaultTerrainTile"; } if (_config.Scale <= 0) { Debug.LogWarning( $"BasicTerrainMapGenerator: Scale must be positive. Setting to default 0.1. Current: {_config.Scale}"); _config.Scale = 0.1; } if (_config.MapCellSizeX <= 0 || _config.MapCellSizeY <= 0) { Debug.LogWarning( $"BasicTerrainMapGenerator: MapCellSizeX or MapCellSizeY is zero or negative. Setting to default (100, 100). Current: ({_config.MapCellSizeX}, {_config.MapCellSizeY})"); _config.MapCellSizeX = 100; _config.MapCellSizeY = 100; } // 新增:MinThreshold 和 MaxThreshold 的校验 // 确保阈值在柏林噪声的合理范围内 (-1.0 到 1.0),假定 PerlinNoise.Instance.Noise 返回此范围 _config.MinThreshold = Math.Max(-1.0, Math.Min(1.0, _config.MinThreshold)); _config.MaxThreshold = Math.Max(-1.0, Math.Min(1.0, _config.MaxThreshold)); if (_config.MinThreshold > _config.MaxThreshold) { Debug.LogWarning( $"BasicTerrainMapGenerator: MinThreshold ({_config.MinThreshold}) cannot be greater than MaxThreshold ({_config.MaxThreshold}). Swapping values."); (_config.MinThreshold, _config.MaxThreshold) = (_config.MaxThreshold, _config.MinThreshold); // 交换值 } } catch (JsonSerializationException ex) { Debug.LogError($"BasicTerrainMapGenerator: JSON deserialization error: {ex.Message}. Input: {value}"); _config = new BasicTerrainGeneratorConfig(); // 失败时使用默认配置 } catch (Exception ex) { Debug.LogError( $"BasicTerrainMapGenerator: An unexpected error occurred during Init: {ex.Message}. Input: {value}"); _config = new BasicTerrainGeneratorConfig(); // 失败时使用默认配置 } } /// /// 根据柏林噪声生成地形。此方法现在是异步的,以避免阻塞主线程。 /// /// MapGenerator实例,包含要操作的Tilemap。 public override async Task Process(MapGenerator map) // 标记为 async Task { if (_config == null) { Debug.LogError( "BasicTerrainMapGenerator: Process called before Init or Init failed. Using default configuration."); _config = new BasicTerrainGeneratorConfig(); // 确保有默认配置 } var terrainTile = TileManager.Instance.GetTile(_config.TileDefName); if (terrainTile == null) { Debug.LogError( $"BasicTerrainMapGenerator: Failed to get tile for defName: '{_config.TileDefName}'. Aborting generation."); return; } // 获取不满足条件时放置的瓦片 TileBase elseTile = null; if (!string.IsNullOrWhiteSpace(_config.ElseTileDefName)) { elseTile = TileManager.Instance.GetTile(_config.ElseTileDefName); if (elseTile == null) { Debug.LogWarning( $"BasicTerrainMapGenerator: Failed to get else-tile for defName: '{_config.ElseTileDefName}'. Will not place else-tiles."); } } 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; // 获取柏林噪声值 (假定 PerlinNoise.Instance.Noise 返回 -1 到 1) var noiseValue = PerlinNoise.Instance.Noise(sampleX, sampleY); // 根据噪声值和阈值范围设置瓦片 if (noiseValue >= _config.MinThreshold && noiseValue <= _config.MaxThreshold) { map.baseTilemap.SetTile(new Vector3Int(x, y, 0), terrainTile); } else if (elseTile != null) // 如果定义了elseTile且成功获取 { map.baseTilemap.SetTile(new Vector3Int(x, y, 0), elseTile); } else { // 如果不满足条件,且没有elseTile定义,则不放置任何瓦片 (兼容旧逻辑,即留空) map.baseTilemap.SetTile(new Vector3Int(x, y, 0), null); } } // 在处理完每一列(或每行)后,暂停,允许Unity渲染帧并处理其他事件。 // 这可以防止长时间的计算阻塞主线程,提高应用程序的响应性。 await Task.Yield(); } } } }