You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请教如何在Unity中实现视频所示的特殊网格机制拼图游戏

Unity拼图游戏特殊网格机制实现方案

核心逻辑拆解

这类特殊网格的核心是每个网格槽有唯一的匹配规则(对应拼图块ID、旋转角度、形状),拖放结束时通过规则校验实现吸附或回弹。以下是具体实现步骤:


1. 定义网格槽数据结构

先为每个网格槽创建数据模板,记录匹配所需的关键信息:

using UnityEngine;

[System.Serializable]
public class PuzzleSlot
{
    public Vector2 gridPosition;       // 网格坐标(用于快速查找)
    public int requiredPieceId;        // 对应拼图块的ID
    public List<float> allowedRotZ;    // 允许的Z轴旋转角度(支持多角度匹配)
    public GameObject slotVisual;      // 网格槽的视觉对象(可选)
}

2. 网格管理器实现

创建一个管理器类,统一管理所有网格槽的初始化、匹配检测:

using UnityEngine;
using System.Collections.Generic;

public class PuzzleGridManager : MonoBehaviour
{
    public List<PuzzleSlot> puzzleSlots;
    private Dictionary<Vector2, PuzzleSlot> slotLookup;

    void Awake()
    {
        slotLookup = new Dictionary<Vector2, PuzzleSlot>();
        foreach (var slot in puzzleSlots)
        {
            slotLookup.Add(slot.gridPosition, slot);
            // 给网格槽添加碰撞触发器(用于精准检测)
            var collider = slot.slotVisual.AddComponent<PolygonCollider2D>();
            collider.isTrigger = true;
            // 如果是矩形槽,可改用BoxCollider2D,更高效
        }
    }

    // 检测当前拼图块是否匹配目标槽
    public bool ValidateMatch(PuzzlePiece piece)
    {
        // 将拼图块世界坐标转为网格坐标(需和槽的gridPosition对应)
        Vector2 gridPos = new Vector2(
            Mathf.Round(piece.transform.position.x),
            Mathf.Round(piece.transform.position.y)
        );

        if (slotLookup.TryGetValue(gridPos, out var targetSlot))
        {
            // 校验ID和旋转角度
            bool idMatch = targetSlot.requiredPieceId == piece.pieceId;
            bool rotMatch = targetSlot.allowedRotZ.Exists(rot => 
                Mathf.Abs(piece.transform.rotation.eulerAngles.z - rot) < 5f
            );
            return idMatch && rotMatch;
        }
        return false;
    }

    // 获取匹配槽的世界位置
    public Vector3 GetSlotWorldPos(PuzzlePiece piece)
    {
        Vector2 gridPos = new Vector2(
            Mathf.Round(piece.transform.position.x),
            Mathf.Round(piece.transform.position.y)
        );
        if (slotLookup.TryGetValue(gridPos, out var slot))
        {
            return new Vector3(slot.gridPosition.x, slot.gridPosition.y, 0);
        }
        return piece.transform.position;
    }
}

3. 拼图块拖放逻辑补充

在你已有的拖放代码中加入匹配校验逻辑:

using UnityEngine;

public class PuzzlePiece : MonoBehaviour
{
    public int pieceId;
    private PuzzleGridManager gridManager;
    private Vector3 startPosition;
    private bool isDragging;

    void Start()
    {
        gridManager = FindObjectOfType<PuzzleGridManager>();
        startPosition = transform.position;
    }

    void OnMouseDown()
    {
        isDragging = true;
        transform.SetParent(null);
    }

    void OnMouseUp()
    {
        isDragging = false;
        // 校验匹配规则
        if (gridManager.ValidateMatch(this))
        {
            // 吸附到网格槽位置
            transform.position = gridManager.GetSlotWorldPos(this);
        }
        else
        {
            // 回弹到初始位置
            transform.position = startPosition;
        }
    }

    void Update()
    {
        if (isDragging)
        {
            Vector3 mouseWorldPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            mouseWorldPos.z = 0;
            transform.position = mouseWorldPos;
        }
        // 可选:添加旋转功能(按空格键旋转)
        if (Input.GetKeyDown(KeyCode.Space))
        {
            transform.Rotate(0, 0, 90);
        }
    }
}

关键优化点

  • 不规则形状匹配:将网格槽的碰撞器替换为PolygonCollider2D,手动绘制和槽形状一致的碰撞区域,确保只有拼图块完全覆盖槽时才触发匹配
  • 视觉反馈:给网格槽添加高亮效果,当拼图块进入槽的碰撞区域且匹配时,触发高亮提示
  • 批量初始化:如果网格数量较多,可以通过代码批量生成网格槽,避免手动配置

内容的提问来源于stack exchange,提问作者lex

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 22:55:16