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

Unity2D设置棋子为棋盘格子子物体时GameObject未创建问题

Unity2D国际象棋棋子无法作为棋盘格子子物体生成

我在做Unity2D国际象棋项目时,遇到一个问题:尝试把棋子设为对应棋盘格子的子物体时,既没有生成新的GameObject,也没有报错。但如果把pieceObj.transform.parent改成当前脚本所在物体的transform,棋子就能正常显示。

相关代码如下:

private void DrawPiece(int piece, Transform parentSquare)
{
    if (!pieceSprites.ContainsKey(piece))
    {
        Debug.LogError($"Piece sprite not found for piece code: {piece}");
        return;
    }

    string pieceBinary = Convert.ToString(piece, 2).PadLeft(5, '0');

    GameObject pieceObj = new GameObject($"Piece_{pieceBinary}@{parentSquare.position.x * 8 + parentSquare.position.y}");
    pieceObj.transform.position = parentSquare.position;

    pieceObj.transform.parent = parentSquare;

    SpriteRenderer sr = pieceObj.AddComponent<SpriteRenderer>();
    sr.sortingOrder = 1;
    sr.sprite = pieceSprites[piece];
    pieceObj.transform.localScale = new Vector3(pieceSize, pieceSize, 1);
}

void DrawAllPieces()
{
    // Clear old pieces
    foreach (Transform child in transform)
    {
        if (child.name.StartsWith("Piece_"))
            Destroy(child.gameObject);
    }

    for (int i = 0; i < 64; i++)
    {
        int piece = Board.Square[i];
        if (piece != Piece.None)
        {
            int x = i % 8;
            int y = i / 8;
            Vector2 position = new Vector2(x - 3.5f, y - 3.5f);

            // Find the square corresponding to the piece's position
            GameObject square = FindSquare(position);
            if (square == null)
            {
                Debug.LogError($"Square not found at position: {position}");
                continue;
            }

            DrawPiece(piece, square.transform);

        }
    }
}

private GameObject FindSquare(Vector2 position) {     
string squareName = $"Square_{position.x + 3.5f}_{position.y + 3.5f}";     return GameObject.Find(squareName); 
}

两种测试效果:

  • 设父物体为格子时:棋盘为空,看不到棋子
  • 设父物体为当前脚本物体时:棋子正常显示在初始位置

排查与解决步骤

1. 调整父物体设置顺序

你当前是先设置棋子的世界位置,再设父物体。Unity会自动把世界坐标转换为父物体的局部坐标,如果格子本身有缩放或者非(0,0,0)的局部位置,会导致棋子偏移到视野外。

修改DrawPiece里的代码顺序,先设父物体,再把棋子的局部位置设为(0,0,0),确保它在格子中心:

GameObject pieceObj = new GameObject($"Piece_{pieceBinary}@{parentSquare.position.x * 8 + parentSquare.position.y}");
// 先设置父物体
pieceObj.transform.parent = parentSquare;
// 直接设置局部位置为格子中心
pieceObj.transform.localPosition = Vector3.zero;

2. 检查格子的渲染层级

虽然你给棋子的sortingOrder设为1,但如果格子的SpriteRenderer的sortingOrder大于等于1,棋子会被格子挡住。打开格子的Inspector面板,确认它的sortingOrder是0或者比1小。

3. 验证格子物体的激活状态

在DrawPiece开头加一行日志,确认找到的格子是激活状态:

private void DrawPiece(int piece, Transform parentSquare)
{
    Debug.Log($"格子状态:{parentSquare.name} | 自身激活:{parentSquare.gameObject.activeSelf} | 层级激活:{parentSquare.gameObject.activeInHierarchy}");
    // 原有代码...
}

如果格子处于禁用状态,要么激活格子,要么在生成棋子后强制激活它:

pieceObj.SetActive(true);

4. 处理格子的缩放问题

如果格子的缩放不是(1,1,1),棋子的localScale会被父物体的缩放影响,导致尺寸异常。可以在设置棋子缩放时抵消父物体的缩放:

// 计算抵消父物体缩放的系数
Vector3 scaleCorrection = new Vector3(1 / parentSquare.localScale.x, 1 / parentSquare.localScale.y, 1);
pieceObj.transform.localScale = new Vector3(pieceSize, pieceSize, 1) * scaleCorrection;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 05:07:30