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

224 lines
9.4 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 Newtonsoft.Json;
using System;
using System.Threading.Tasks; // 引入 System.Threading.Tasks
using Managers;
using Utils;
namespace Map
{
/// <summary>
/// 植物生成器配置类。
/// </summary>
public class PlantGeneratorConfig
{
/// <summary>
/// 植物瓦片的定义名称。
/// </summary>
[JsonProperty("tileDefName", Required = Required.Always)]
public string TileDefName { get; set; } = "DefaultPlantTile";
/// <summary>
/// 柏林噪声的缩放因子。
/// </summary>
[JsonProperty("scale")]
public double Scale { get; set; } = 0.08;
/// <summary>
/// 柏林噪声阈值,高于此值才可能生成植物 (-1到1之间)。
/// </summary>
[JsonProperty("threshold")]
public double Threshold { get; set; } = 0.3;
/// <summary>
/// 植物生成概率 (0-1之间),控制稀疏度。
/// </summary>
[JsonProperty("density")]
public double Density { get; set; } = 0.6;
/// <summary>
/// 柏林噪声的X轴偏移。
/// </summary>
[JsonProperty("offsetX")]
public double OffsetX { get; set; } = 0.0;
/// <summary>
/// 柏林噪声的Y轴偏移。
/// </summary>
[JsonProperty("offsetY")]
public double OffsetY { get; set; } = 0.0;
/// <summary>
/// 植物必须生长在其上的基础瓦片名称 (可空)。
/// </summary>
[JsonProperty("requiredBaseTileDefName")]
public string RequiredBaseTileDefName { get; set; } = null;
/// <summary>
/// 地图生成区域的宽度(单元格数量)。
/// </summary>
[JsonProperty("mapCellSizeX")]
public int MapCellSizeX { get; set; } = 100;
/// <summary>
/// 地图生成区域的高度(单元格数量)。
/// </summary>
[JsonProperty("mapCellSizeY")]
public int MapCellSizeY { get; set; } = 100;
/// <summary>
/// 是否避免植物瓦片互相重叠。
/// </summary>
[JsonProperty("preventOverlap")]
public bool PreventOverlap { get; set; } = true;
}
public class PlantMapGenerator : MapGeneratorWorkClassBase
{
private PlantGeneratorConfig _config;
/// <summary>
/// 初始化植物生成器解析JSON配置字符串。
/// </summary>
/// <param name="value">包含植物生成参数的JSON字符串。</param>
public override void Init(string value)
{
try
{
_config = JsonConvert.DeserializeObject<PlantGeneratorConfig>(value);
if (_config == null)
{
Debug.LogError("植物地图生成器配置反序列化为空。请检查JSON格式。将使用默认配置。");
_config = new PlantGeneratorConfig();
}
if (string.IsNullOrWhiteSpace(_config.TileDefName))
{
Debug.LogWarning("植物地图生成器:瓦片定义名称为空。将使用默认值 'DefaultPlantTile'。");
_config.TileDefName = "DefaultPlantTile";
}
if (_config.Scale <= 0)
{
Debug.LogWarning($"植物地图生成器:缩放值必须为正数。将设置为默认值 0.08。当前值: {_config.Scale}");
_config.Scale = 0.08;
}
// Unity的Mathf.PerlinNoise输出0-1如果PerlinNoise.Instance.Noise也如此这里需要修改范围
// 假设 PerlinNoise.Instance.Noise() 返回值在 -1 到 1 之间。
if (_config.Threshold < -1.0 || _config.Threshold > 1.0)
{
Debug.LogWarning($"植物地图生成器:阈值 ({_config.Threshold}) 超出柏林噪声典型范围 (-1.0到1.0)。已钳制到 0.3。");
_config.Threshold = 0.3;
}
if (_config.Density < 0 || _config.Density > 1)
{
Debug.LogWarning($"植物地图生成器:密度 ({_config.Density}) 必须在 0 到 1 之间。已钳制到 0.6。");
_config.Density = Mathf.Clamp((float)_config.Density, 0f, 1f);
}
if (_config.MapCellSizeX <= 0)
{
Debug.LogWarning($"植物地图生成器:地图宽度 ({_config.MapCellSizeX}) 必须为正数。将设置为默认值 100。");
_config.MapCellSizeX = 100;
}
if (_config.MapCellSizeY <= 0)
{
Debug.LogWarning($"植物地图生成器:地图高度 ({_config.MapCellSizeY}) 必须为正数。将设置为默认值 100。");
_config.MapCellSizeY = 100;
}
}
catch (JsonSerializationException ex)
{
Debug.LogError($"植物地图生成器配置JSON反序列化错误{ex.Message}。输入JSON: '{value}'");
_config = new PlantGeneratorConfig();
}
catch (Exception ex)
{
Debug.LogError($"植物地图生成器:初始化过程中发生未预期错误:{ex.Message}。输入JSON: '{value}'");
_config = new PlantGeneratorConfig();
}
}
/// <summary>
/// 根据柏林噪声和配置参数在 `MapGenerator` 的 `plantTilemap` 上生成植物。
/// 此方法现在是异步的,以避免阻塞主线程。
/// </summary>
/// <param name="map">MapGenerator实例包含要操作的Tilemap。</param>
public override async Task Process(MapGenerator map) // 标记为 async Task
{
if (_config == null)
{
Debug.LogError("植物地图生成器在Init方法调用前或Init失败后调用Process。中止生成。");
return; // async Task 方法直接 return; 意味着返回 Task.CompletedTask
}
if (map == null || map.plantTilemap == null)
{
Debug.LogError("植物地图生成器MapGenerator或植物瓦片地图为空。无法生成植物。中止。");
return;
}
var plantTile = TileManager.Instance.GetTile(_config.TileDefName);
if (plantTile == null)
{
Debug.LogError($"植物地图生成器:无法获取名称为 '{_config.TileDefName}' 的瓦片。请确保瓦片管理器返回有效瓦片。中止生成。");
return;
}
// 缓存 requiredBaseTile 的引用,避免在循环中重复查询 TileManager
UnityEngine.Tilemaps.TileBase requiredBaseTile = null;
if (!string.IsNullOrEmpty(_config.RequiredBaseTileDefName))
{
if (map.baseTilemap == null)
{
Debug.LogWarning($"植物地图生成器:已配置基础瓦片名称 ('{_config.RequiredBaseTileDefName}') 但基础瓦片地图为空。将忽略基础地形要求。");
}
else
{
requiredBaseTile = TileManager.Instance.GetTile(_config.RequiredBaseTileDefName);
if (requiredBaseTile == null)
{
Debug.LogWarning($"植物地图生成器:无法获取所需的基础瓦片 '{_config.RequiredBaseTileDefName}'。将忽略基础地形要求。");
}
}
}
for (var x = 0; x < _config.MapCellSizeX; x++)
{
for (var y = 0; y < _config.MapCellSizeY; y++)
{
var cellPosition = new Vector3Int(x, y, 0);
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);
if (noiseValue < _config.Threshold)
{
continue;
}
// 检查所需的基础瓦片
if (requiredBaseTile != null)
{
var baseTileOnMap = map.baseTilemap.GetTile(cellPosition);
if (baseTileOnMap == null || baseTileOnMap.name != requiredBaseTile.name)
{
continue;
}
}
// 检查是否重叠
if (_config.PreventOverlap)
{
var existingPlant = map.plantTilemap.GetTile(cellPosition);
if (existingPlant != null)
{
continue;
}
}
// 检查密度
if (UnityEngine.Random.value >= _config.Density)
{
continue;
}
map.plantTilemap.SetTile(cellPosition, plantTile);
}
// 每处理完一列,就让出控制权给主线程
await Task.Yield();
}
}
}
}