using System.Collections.Generic; using UnityEngine; namespace AibisDream { /// /// 网格可视化组件 /// 负责在Unity场景中可视化显示网格和单元格状态 /// 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(); } /// /// 初始化网格 /// public void InitializeGrid() { // 优先使用外部网格组件 if (gridComponent != null) { // 如果组件还没有初始化,先初始化它 if (!gridComponent.IsInitialized()) { gridComponent.Initialize(); } _grid = gridComponent; } else { // 如果没有外部网格,创建内部网格组件 if (_internalGrid == null) { _internalGrid = gameObject.GetComponent(); if (_internalGrid == null) { _internalGrid = gameObject.AddComponent(); } } _internalGrid.Initialize(gridWidth, gridHeight, cellSize, transform.position); _grid = _internalGrid; } CreateVisualization(); } /// /// 设置网格引用 /// public void SetGrid(IBlockPuzzleGrid grid) { _grid = grid; ClearVisualization(); CreateVisualization(); } /// /// 创建可视化 /// private void CreateVisualization() { if (_grid == null) return; if (showGridLines) { DrawGridLines(); } if (showCellSprites) { CreateCellSprites(); } } /// /// 绘制网格线 /// 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 ); } } /// /// 创建一条线 /// 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.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; } /// /// 创建单元格精灵 /// private void CreateCellSprites() { // 清除旧的单元格 ClearCellSprites(); // 为每个单元格创建可视化对象 for (int x = 0; x < _grid.Width; x++) { for (int y = 0; y < _grid.Height; y++) { CreateCellSprite(x, y); } } } /// /// 创建单个单元格精灵 /// 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(); // 如果没有指定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; } /// /// 创建默认的白色Sprite /// 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); } /// /// 更新单元格可视化状态 /// public void UpdateCellVisual(int x, int y) { if (!_cellObjects.TryGetValue((x, y), out GameObject cellObj)) { return; } SpriteRenderer spriteRenderer = cellObj.GetComponent(); if (spriteRenderer == null) return; GridCellState state = _grid.GetCellState(x, y); spriteRenderer.color = state == GridCellState.Occupied ? occupiedCellColor : emptyCellColor; } /// /// 更新所有单元格可视化 /// 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); } } } /// /// 清除单元格精灵 /// private void ClearCellSprites() { foreach (var kvp in _cellObjects) { if (Application.isPlaying) { Destroy(kvp.Value); } else { DestroyImmediate(kvp.Value); } } _cellObjects.Clear(); } /// /// 清除所有可视化 /// 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); } } }