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

204 lines
9.9 KiB
C#
Raw Permalink Normal View History

using System;
using System.Threading.Tasks;
using Managers;
using Newtonsoft.Json;
using UnityEngine;
using UnityEngine.Tilemaps;
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;
/// <summary>
/// 初始化地形生成器解析JSON配置字符串。
/// </summary>
/// <param name="value">包含地形生成参数的JSON字符串。</param>
public override void Init(string value)
{
try
{
_config = JsonConvert.DeserializeObject<BasicTerrainGeneratorConfig>(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(); // 失败时使用默认配置
}
}
/// <summary>
/// 根据柏林噪声生成地形。此方法现在是异步的,以避免阻塞主线程。
/// </summary>
/// <param name="landform">地图生成器实例,包含要操作的瓦片地图。</param>
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 相加,用于指定瓦片的实际放置位置。
var 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();
}
}
/// <summary>
/// 获取当前配置的地图尺寸。
/// </summary>
/// <returns>表示地图宽度和高度的 Vector2Int。</returns>
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);
}
}
}