(client) feat:支持定义实体的碰撞体大小和偏移;建筑支持定义实体建筑和瓦片建筑,建筑支持指定按钮回调;添加存档管理器;Dev支持设置是否暂停;实体允许定义事件组;添加基地界面 (#57)

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/57
This commit is contained in:
2025-09-28 15:02:57 +08:00
parent 87a8abe86c
commit aff747be17
232 changed files with 39203 additions and 4161 deletions

View File

@@ -2,12 +2,19 @@ using UnityEngine;
using UnityEngine.Tilemaps;
using Newtonsoft.Json;
using System;
using System.Threading.Tasks; // 引入 System.Threading.Tasks
using System.Threading.Tasks;
using Managers;
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)]
@@ -15,25 +22,30 @@ namespace Map
// 将 Threshold 改为 MinThreshold并保持旧的JsonProperty名称以兼容旧JSON
[JsonProperty("threshold")]
public double MinThreshold { get; set; } = 0.0; // 柏林噪声的最小阈值。0到1之间。将其默认值改为0.0以适应-1到1的噪声范围并提供更灵活的区间开始。
public double MinThreshold { get; set; } // 柏林噪声的最小阈值。-1到1之间。将其默认值改为0.0以适应-1到1的噪声范围并提供更灵活的区间开始。
[JsonProperty("maxThreshold")]
public double MaxThreshold { get; set; } = 1.0; // 柏林噪声的最大阈值。0到1之间。默认为1.0以兼容旧配置。
[JsonProperty("maxThreshold")] public double MaxThreshold { get; set; } = 1.0; // 柏林噪声的最大阈值。-1到1之间。默认为1.0以兼容旧配置。
[JsonProperty("elseTileDefName")]
public string ElseTileDefName { get; set; } = null; // 不满足Min/MaxThreshold范围时放置的瓦片定义名称默认为null表示不放置。
public string ElseTileDefName { get; set; } // 不满足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("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; }
}
// BasicTerrainGeneratorConfig 应该在同一个文件或者它自己的文件中定义,
// 这里为了清晰展示修改,假定它在 Map 命名空间下可用。
// MapDimension 枚举在此文件中不重复定义,因为它通常位于自己的文件中或 Map 命名空间的其他通用文件中。
// 如果它与 BasicTerrainGeneratorConfig 在同一个文件,则在 BasicTerrainGeneratorConfig 定义后。
public class BasicTerrainMapGenerator : MapGeneratorWorkClassBase
{
private BasicTerrainGeneratorConfig _config;
@@ -47,57 +59,52 @@ namespace Map
try
{
_config = JsonConvert.DeserializeObject<BasicTerrainGeneratorConfig>(value);
// 参数有效性检查
// _config 不是单例,所以需要进行空检查。
if (_config == null)
{
Debug.LogError("BasicTerrainMapGenerator: Configuration deserialized to null. Check JSON format.");
_config = new BasicTerrainGeneratorConfig(); // 提供默认配置以防崩溃
Debug.LogError("基本地形生成器: 配置反序列化为空。请检查JSON格式。");
_config = new BasicTerrainGeneratorConfig();
}
if (string.IsNullOrWhiteSpace(_config.TileDefName))
{
Debug.LogWarning(
"BasicTerrainMapGenerator: TileDefName is empty. Using default 'DefaultTerrainTile'.");
Debug.LogWarning("基本地形生成器: 瓦片定义名称为空。使用默认值 'DefaultTerrainTile'。");
_config.TileDefName = "DefaultTerrainTile";
}
if (_config.Scale <= 0)
{
Debug.LogWarning(
$"BasicTerrainMapGenerator: Scale must be positive. Setting to default 0.1. Current: {_config.Scale}");
Debug.LogWarning($"基本地形生成器: 缩放值必须为正。设置为默认值 0.1。当前值: {_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})");
$"基本地形生成器: 地图单元格宽度或高度为零或负数。设置为默认值 (100, 100)。当前值: ({_config.MapCellSizeX}, {_config.MapCellSizeY})");
_config.MapCellSizeX = 100;
_config.MapCellSizeY = 100;
}
// 新增MinThreshold 和 MaxThreshold 的校验
// 确保阈值在柏林噪声的合理范围内 (-1.0 到 1.0),假定 PerlinNoise.Instance.Noise 返回此范围
// 将阈值限定在 -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(
$"BasicTerrainMapGenerator: MinThreshold ({_config.MinThreshold}) cannot be greater than MaxThreshold ({_config.MaxThreshold}). Swapping values.");
$"基本地形生成器: 最小阈值 ({_config.MinThreshold}) 不能大于最大阈值 ({_config.MaxThreshold})。交换值。");
(_config.MinThreshold, _config.MaxThreshold) = (_config.MaxThreshold, _config.MinThreshold); // 交换值
}
}
catch (JsonSerializationException ex)
{
Debug.LogError($"BasicTerrainMapGenerator: JSON deserialization error: {ex.Message}. Input: {value}");
Debug.LogError($"基本地形生成器: JSON反序列化错误: {ex.Message}。输入: {value}");
_config = new BasicTerrainGeneratorConfig(); // 失败时使用默认配置
}
catch (Exception ex)
{
Debug.LogError(
$"BasicTerrainMapGenerator: An unexpected error occurred during Init: {ex.Message}. Input: {value}");
Debug.LogError($"基本地形生成器: Init 期间发生意外错误: {ex.Message}。输入: {value}");
_config = new BasicTerrainGeneratorConfig(); // 失败时使用默认配置
}
}
@@ -105,70 +112,101 @@ namespace Map
/// <summary>
/// 根据柏林噪声生成地形。此方法现在是异步的,以避免阻塞主线程。
/// </summary>
/// <param name="map">MapGenerator实例,包含要操作的Tilemap。</param>
public override async Task Process(MapGenerator map) // 标记为 async Task
/// <param name="landform">地图生成器实例,包含要操作的瓦片地图。</param>
public override async Task Process(Landform landform)
{
// _config 不是单例,所以需要进行空检查。
if (_config == null)
{
Debug.LogError(
"BasicTerrainMapGenerator: Process called before Init or Init failed. Using default configuration.");
_config = new BasicTerrainGeneratorConfig(); // 确保有默认配置
Debug.LogError("基本地形生成器: Process 在 Init 之前调用或 Init 失败。使用默认配置。");
_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.");
Debug.LogError($"基本地形生成器: 无法获取瓦片定义名称: '{_config.TileDefName}'。中止生成。");
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.");
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;
// 获取柏林噪声值 (假定 PerlinNoise.Instance.Noise 返回 -1 到 1)
var noiseValue = PerlinNoise.Instance.Noise(sampleX, sampleY);
// 根据噪声值和阈值范围设置瓦片
// 核心修改部分:将 x, y 与 OriginX, OriginY 相加,用于指定瓦片的实际放置位置。
Vector3Int tilePosition = new Vector3Int(x + _config.OriginX, y + _config.OriginY, 0);
if (noiseValue >= _config.MinThreshold && noiseValue <= _config.MaxThreshold)
{
map.baseTilemap.SetTile(new Vector3Int(x, y, 0), terrainTile);
targetTilemap.SetTile(tilePosition, terrainTile);
}
else if (elseTile != null) // 如果定义了elseTile且成功获取
else if (elseTile != null)
{
map.baseTilemap.SetTile(new Vector3Int(x, y, 0), elseTile);
targetTilemap.SetTile(tilePosition, elseTile);
}
else
{
// 如果不满足条件且没有elseTile定义则不放置任何瓦片 (兼容旧逻辑,即留空)
map.baseTilemap.SetTile(new Vector3Int(x, y, 0), null);
targetTilemap.SetTile(tilePosition, null);
}
}
// 在处理完每一列或每行暂停允许Unity渲染帧并处理其他事件。
// 这可以防止长时间的计算阻塞主线程,提高应用程序的响应性。
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);
}
}
}