mirror of
http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite.git
synced 2025-11-20 06:47:14 +08:00
Co-authored-by: m0_75251201 <m0_75251201@noreply.gitcode.com> Reviewed-on: http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite/pulls/56
175 lines
8.3 KiB
C#
175 lines
8.3 KiB
C#
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();
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
}
|
||
|