338 lines
10 KiB
C#
338 lines
10 KiB
C#
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
namespace AibisDream
|
||
{
|
||
/// <summary>
|
||
/// 网格可视化组件
|
||
/// 负责在Unity场景中可视化显示网格和单元格状态
|
||
/// </summary>
|
||
public class GridVisualizer : MonoBehaviour
|
||
{
|
||
[Header("网格配置")]
|
||
[SerializeField] private BlockPuzzleGrid gridComponent;
|
||
[SerializeField] private int gridWidth = 10;
|
||
[SerializeField] private int gridHeight = 10;
|
||
[SerializeField] private float cellSize = 1f;
|
||
|
||
private IBlockPuzzleGrid _grid;
|
||
|
||
[Header("可视化设置")]
|
||
[SerializeField] private bool showGridLines = true;
|
||
[SerializeField] private bool showCellSprites = true;
|
||
[SerializeField] private Color emptyCellColor = new Color(0.9f, 0.9f, 0.9f, 0.3f);
|
||
[SerializeField] private Color occupiedCellColor = new Color(0.2f, 0.6f, 1f, 1f);
|
||
[SerializeField] private Color gridLineColor = new Color(0.5f, 0.5f, 0.5f, 0.5f);
|
||
[SerializeField] private float gridLineWidth = 0.02f;
|
||
|
||
[Header("预制体(可选)")]
|
||
[SerializeField] private Sprite cellSprite;
|
||
[SerializeField] private Material cellMaterial;
|
||
|
||
// 单元格可视化对象池
|
||
private Dictionary<(int x, int y), GameObject> _cellObjects = new Dictionary<(int x, int y), GameObject>();
|
||
private GameObject _gridLinesParent;
|
||
private GameObject _cellsParent;
|
||
private BlockPuzzleGrid _internalGrid;
|
||
|
||
private void Awake()
|
||
{
|
||
// 创建父对象用于组织层级
|
||
_gridLinesParent = new GameObject("GridLines");
|
||
_gridLinesParent.transform.SetParent(transform);
|
||
_gridLinesParent.transform.localPosition = Vector3.zero;
|
||
|
||
_cellsParent = new GameObject("Cells");
|
||
_cellsParent.transform.SetParent(transform);
|
||
_cellsParent.transform.localPosition = Vector3.zero;
|
||
}
|
||
|
||
private void Start()
|
||
{
|
||
InitializeGrid();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化网格
|
||
/// </summary>
|
||
public void InitializeGrid()
|
||
{
|
||
// 优先使用外部网格组件
|
||
if (gridComponent != null)
|
||
{
|
||
// 如果组件还没有初始化,先初始化它
|
||
if (!gridComponent.IsInitialized())
|
||
{
|
||
gridComponent.Initialize();
|
||
}
|
||
_grid = gridComponent;
|
||
}
|
||
else
|
||
{
|
||
// 如果没有外部网格,创建内部网格组件
|
||
if (_internalGrid == null)
|
||
{
|
||
_internalGrid = gameObject.GetComponent<BlockPuzzleGrid>();
|
||
if (_internalGrid == null)
|
||
{
|
||
_internalGrid = gameObject.AddComponent<BlockPuzzleGrid>();
|
||
}
|
||
}
|
||
_internalGrid.Initialize(gridWidth, gridHeight, cellSize, transform.position);
|
||
_grid = _internalGrid;
|
||
}
|
||
|
||
CreateVisualization();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置网格引用
|
||
/// </summary>
|
||
public void SetGrid(IBlockPuzzleGrid grid)
|
||
{
|
||
_grid = grid;
|
||
ClearVisualization();
|
||
CreateVisualization();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建可视化
|
||
/// </summary>
|
||
private void CreateVisualization()
|
||
{
|
||
if (_grid == null) return;
|
||
|
||
if (showGridLines)
|
||
{
|
||
DrawGridLines();
|
||
}
|
||
|
||
if (showCellSprites)
|
||
{
|
||
CreateCellSprites();
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 绘制网格线
|
||
/// </summary>
|
||
private void DrawGridLines()
|
||
{
|
||
// 清除旧的网格线
|
||
foreach (Transform child in _gridLinesParent.transform)
|
||
{
|
||
if (Application.isPlaying)
|
||
{
|
||
Destroy(child.gameObject);
|
||
}
|
||
else
|
||
{
|
||
DestroyImmediate(child.gameObject);
|
||
}
|
||
}
|
||
|
||
// 创建网格线(使用LineRenderer或简单的Quad)
|
||
for (int x = 0; x <= _grid.Width; x++)
|
||
{
|
||
CreateLine(
|
||
_grid.GridVerticesToWorld(x, 0)[0],
|
||
_grid.GridVerticesToWorld(x, _grid.Height)[0],
|
||
gridLineWidth,
|
||
gridLineColor
|
||
);
|
||
}
|
||
|
||
for (int y = 0; y <= _grid.Height; y++)
|
||
{
|
||
CreateLine(
|
||
_grid.GridVerticesToWorld(0, y)[0],
|
||
_grid.GridVerticesToWorld(_grid.Width, y)[0],
|
||
gridLineWidth,
|
||
gridLineColor
|
||
);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建一条线
|
||
/// </summary>
|
||
private void CreateLine(Vector3 start, Vector3 end, float width, Color color)
|
||
{
|
||
GameObject lineObj = new GameObject("GridLine");
|
||
lineObj.transform.SetParent(_gridLinesParent.transform);
|
||
lineObj.transform.localPosition = Vector3.zero;
|
||
|
||
LineRenderer lineRenderer = lineObj.AddComponent<LineRenderer>();
|
||
lineRenderer.useWorldSpace = true;
|
||
lineRenderer.positionCount = 2;
|
||
lineRenderer.SetPosition(0, start);
|
||
lineRenderer.SetPosition(1, end);
|
||
lineRenderer.startWidth = width;
|
||
lineRenderer.endWidth = width;
|
||
lineRenderer.material = new Material(Shader.Find("Sprites/Default"));
|
||
lineRenderer.startColor = color;
|
||
lineRenderer.endColor = color;
|
||
lineRenderer.sortingOrder = 0;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建单元格精灵
|
||
/// </summary>
|
||
private void CreateCellSprites()
|
||
{
|
||
// 清除旧的单元格
|
||
ClearCellSprites();
|
||
|
||
// 为每个单元格创建可视化对象
|
||
for (int x = 0; x < _grid.Width; x++)
|
||
{
|
||
for (int y = 0; y < _grid.Height; y++)
|
||
{
|
||
CreateCellSprite(x, y);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建单个单元格精灵
|
||
/// </summary>
|
||
private void CreateCellSprite(int x, int y)
|
||
{
|
||
GameObject cellObj = new GameObject($"Cell_{x}_{y}");
|
||
cellObj.transform.SetParent(_cellsParent.transform);
|
||
cellObj.transform.position = _grid.GridToWorld(x, y);
|
||
|
||
SpriteRenderer spriteRenderer = cellObj.AddComponent<SpriteRenderer>();
|
||
|
||
// 如果没有指定Sprite,创建一个简单的白色Sprite
|
||
if (cellSprite == null)
|
||
{
|
||
cellSprite = CreateDefaultSprite();
|
||
}
|
||
|
||
spriteRenderer.sprite = cellSprite;
|
||
spriteRenderer.color = emptyCellColor;
|
||
spriteRenderer.sortingOrder = 1;
|
||
|
||
// 设置大小
|
||
float spriteSize = _grid.CellSize * 0.9f; // 稍微小一点,留出网格线空间
|
||
cellObj.transform.localScale = new Vector3(spriteSize, spriteSize, 1f);
|
||
|
||
// 如果有材质,应用材质
|
||
if (cellMaterial != null)
|
||
{
|
||
spriteRenderer.material = cellMaterial;
|
||
}
|
||
|
||
_cellObjects[(x, y)] = cellObj;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 创建默认的白色Sprite
|
||
/// </summary>
|
||
private Sprite CreateDefaultSprite()
|
||
{
|
||
Texture2D texture = new Texture2D(1, 1);
|
||
texture.SetPixel(0, 0, Color.white);
|
||
texture.Apply();
|
||
return Sprite.Create(texture, new Rect(0, 0, 1, 1), new Vector2(0.5f, 0.5f), 1f);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新单元格可视化状态
|
||
/// </summary>
|
||
public void UpdateCellVisual(int x, int y)
|
||
{
|
||
if (!_cellObjects.TryGetValue((x, y), out GameObject cellObj))
|
||
{
|
||
return;
|
||
}
|
||
|
||
SpriteRenderer spriteRenderer = cellObj.GetComponent<SpriteRenderer>();
|
||
if (spriteRenderer == null) return;
|
||
|
||
GridCellState state = _grid.GetCellState(x, y);
|
||
spriteRenderer.color = state == GridCellState.Occupied ? occupiedCellColor : emptyCellColor;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 更新所有单元格可视化
|
||
/// </summary>
|
||
public void UpdateAllCellsVisual()
|
||
{
|
||
if (_grid == null) return;
|
||
|
||
for (int x = 0; x < _grid.Width; x++)
|
||
{
|
||
for (int y = 0; y < _grid.Height; y++)
|
||
{
|
||
UpdateCellVisual(x, y);
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除单元格精灵
|
||
/// </summary>
|
||
private void ClearCellSprites()
|
||
{
|
||
foreach (var kvp in _cellObjects)
|
||
{
|
||
if (Application.isPlaying)
|
||
{
|
||
Destroy(kvp.Value);
|
||
}
|
||
else
|
||
{
|
||
DestroyImmediate(kvp.Value);
|
||
}
|
||
}
|
||
_cellObjects.Clear();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 清除所有可视化
|
||
/// </summary>
|
||
private void ClearVisualization()
|
||
{
|
||
ClearCellSprites();
|
||
|
||
foreach (Transform child in _gridLinesParent.transform)
|
||
{
|
||
if (Application.isPlaying)
|
||
{
|
||
Destroy(child.gameObject);
|
||
}
|
||
else
|
||
{
|
||
DestroyImmediate(child.gameObject);
|
||
}
|
||
}
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
ClearVisualization();
|
||
}
|
||
|
||
// 在编辑器中预览网格
|
||
private void OnDrawGizmos()
|
||
{
|
||
if (_grid == null) return;
|
||
|
||
// 绘制网格边界
|
||
Gizmos.color = gridLineColor;
|
||
Vector3 bottomLeft = _grid.GridToWorld(0, 0);
|
||
Vector3 bottomRight = _grid.GridToWorld(_grid.Width, 0);
|
||
Vector3 topLeft = _grid.GridToWorld(0, _grid.Height);
|
||
Vector3 topRight = _grid.GridToWorld(_grid.Width, _grid.Height);
|
||
|
||
Gizmos.DrawLine(bottomLeft, bottomRight);
|
||
Gizmos.DrawLine(bottomRight, topRight);
|
||
Gizmos.DrawLine(topRight, topLeft);
|
||
Gizmos.DrawLine(topLeft, bottomLeft);
|
||
}
|
||
}
|
||
}
|
||
|