Files
aibis-dream/Assets/Scripts/MiniGame/BlockPuzzle/Class/GridVisualizer.cs
T
2025-12-11 23:42:41 +08:00

370 lines
12 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 System.Collections.Generic;
using UnityEngine;
namespace AibisDream
{
/// <summary>
/// 网格可视化组件
/// 负责在Unity场景中可视化显示网格和单元格状态
/// </summary>
public class GridVisualizer : MonoBehaviour
{
[Header("网格配置")]
[SerializeField] private BlockPuzzleGrid grid;
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;
[HideInInspector] public int sortingLayer;
[HideInInspector] public int sortingOrder;
// 单元格可视化对象池
private Dictionary<(int x, int y), GameObject> _cellObjects = new Dictionary<(int x, int y), GameObject>();
private GameObject _gridLinesParent;
private GameObject _cellsParent;
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;
}
/// <summary>
/// 设置网格引用
/// </summary>
public void Init(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();
}
// ============================================ 绘制预览 ============================================
/// <summary>
/// 在编辑器中绘制网格预览
/// </summary>
private void OnDrawGizmos()
{
if (grid == null) return;
// 使用当前Inspector中的参数或已初始化的参数
int drawWidth = grid.width;
int drawHeight = grid.height;
float drawCellSize = grid.cellSize;
Vector3 drawOrigin = transform.position;
if (drawWidth <= 0 || drawHeight <= 0 || drawCellSize <= 0) return;
// 绘制网格线
Gizmos.color = gridLineColor;
for (int x = 0; x <= drawWidth; x++)
{
Vector3 start = drawOrigin + new Vector3(x * drawCellSize, 0, 0);
Vector3 end = drawOrigin + new Vector3(x * drawCellSize, drawHeight * drawCellSize, 0);
Gizmos.DrawLine(start, end);
}
for (int y = 0; y <= drawHeight; y++)
{
Vector3 start = drawOrigin + new Vector3(0, y * drawCellSize, 0);
Vector3 end = drawOrigin + new Vector3(drawWidth * drawCellSize, y * drawCellSize, 0);
Gizmos.DrawLine(start, end);
}
// 绘制单元格状态(如果已初始化且启用)
if (_grid != null)
{
float cellDisplaySize = drawCellSize * 0.9f; // 稍微小一点,留出网格线空间
Vector3 cellSizeVec = new Vector3(cellDisplaySize, cellDisplaySize, 0.01f);
for (int x = 0; x < drawWidth; x++)
{
for (int y = 0; y < drawHeight; y++)
{
if (grid.IsValidPosition(x, y))
{
Vector3 cellCenter = grid.GridToWorld(x, y);
GridCellState state = grid.GetCellState(x, y);
Gizmos.color = state == GridCellState.Occupied ? occupiedCellColor : emptyCellColor;
Gizmos.DrawCube(cellCenter, cellSizeVec);
}
}
}
}
}
/// <summary>
/// 选中时绘制更明显的网格边界
/// </summary>
private void OnDrawGizmosSelected()
{
if (grid == null) return;
// 使用当前Inspector中的参数或已初始化的参数
int drawWidth = grid.width;
int drawHeight = grid.height;
float drawCellSize = grid.cellSize;
Vector3 drawOrigin = transform.position;
if (drawWidth <= 0 || drawHeight <= 0 || drawCellSize <= 0) return;
// 绘制网格边界(更粗的线)
Gizmos.color = new Color(gridLineColor.r, gridLineColor.g, gridLineColor.b, 1f);
Vector3 bottomLeft = drawOrigin;
Vector3 bottomRight = drawOrigin + new Vector3(drawWidth * drawCellSize, 0, 0);
Vector3 topLeft = drawOrigin + new Vector3(0, drawHeight * drawCellSize, 0);
Vector3 topRight = drawOrigin + new Vector3(drawWidth * drawCellSize, drawHeight * drawCellSize, 0);
// 绘制边界框
Gizmos.DrawLine(bottomLeft, bottomRight);
Gizmos.DrawLine(bottomRight, topRight);
Gizmos.DrawLine(topRight, topLeft);
Gizmos.DrawLine(topLeft, bottomLeft);
// 绘制原点标记
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(drawOrigin, 0.1f);
}
}
}