Files
Gen_Hack-and-Slash-Roguelite/Client/Assets/Scripts/Map/BasicTerrainMapGenerator.cs

175 lines
8.3 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.

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;
/// <summary>
/// 初始化地形生成器解析JSON配置字符串。
/// </summary>
/// <param name="value">包含地形生成参数的JSON字符串。</param>
public override void Init(string value)
{
try
{
_config = JsonConvert.DeserializeObject<BasicTerrainGeneratorConfig>(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(); // 失败时使用默认配置
}
}
/// <summary>
/// 根据柏林噪声生成地形。此方法现在是异步的,以避免阻塞主线程。
/// </summary>
/// <param name="map">MapGenerator实例包含要操作的Tilemap。</param>
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();
}
}
}
}