370 lines
12 KiB
C#
370 lines
12 KiB
C#
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);
|
||
}
|
||
}
|
||
}
|
||
|