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

Unity中使用SetParent后GameObject运行时消失的修复方法

问题

开发类似Bookworm的游戏时,将LetterTile设置为子物体后,运行时物体莫名消失(编辑器中显示正常,且物体未被销毁)。以下是设置父物体的逻辑代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class ParentSetter : MonoBehaviour
{
    public bool IsOnSlot = false;
    public GameObject[] LetterInputTile;
    public GameObject letterInputTileParent;
    // Start is called before the first frame update
    void Start()
    {
        letterInputTileParent = new GameObject("LetterInputTileParent");
    }

    // Update is called once per frame
    void Update()
    {
        if(IsOnSlot)
        {
            for (int i = 0; i < LetterInputTile.Length; i++)
            {
                LetterInputTile[i].transform.SetParent(letterInputTileParent.transform);
            }
        }
        else
        {
            for (int i = 0; i < LetterInputTile.Length; i++)
            {
                LetterInputTile[i].transform.SetParent(null);
            }
        }
    }

    private void OnCollisionEnter2D(Collision2D other)
    {
        if(other.gameObject.CompareTag("MLetterTile"))
        {
            IsOnSlot = true;
        }
    }

    private void OnCollisionExit2D(Collision2D other)
    {
        if (other.gameObject.CompareTag("MLetterTile"))
        {
            IsOnSlot = false;
        }
    }
}

修复方案

问题根源

  1. 动态父物体层级错误:Start()中创建的letterInputTileParent默认处于场景根节点,若LetterTile是UI元素(依赖Canvas渲染),将其挂载到非Canvas父物体下会导致UI无法渲染,视觉上表现为消失。
  2. 重复执行父物体设置:Update()中每一帧都重复调用SetParent,会触发Transform的频繁重计算,可能导致层级异常或性能损耗。
  3. 碰撞逻辑缺陷:多个LetterTile碰撞时,IsOnSlot会被反复切换,导致父物体设置逻辑混乱。

具体修复步骤

1. 给动态父物体指定正确层级

如果LetterTile是UI元素,必须将父物体挂载到Canvas下,确保UI渲染正常:

void Start()
{
    letterInputTileParent = new GameObject("LetterInputTileParent");
    // 绑定到场景中的Canvas
    Canvas canvas = FindObjectOfType<Canvas>();
    if (canvas != null)
    {
        letterInputTileParent.transform.SetParent(canvas.transform);
    }
    // 添加RectTransform组件,适配UI布局
    letterInputTileParent.AddComponent<RectTransform>();
}

2. 避免重复执行父物体设置

仅在IsOnSlot状态变化时执行设置逻辑,减少不必要的计算:

private bool _lastIsOnSlot;

void Update()
{
    if (IsOnSlot != _lastIsOnSlot)
    {
        _lastIsOnSlot = IsOnSlot;
        foreach (GameObject tile in LetterInputTile)
        {
            if (tile == null) continue;
            
            tile.transform.SetParent(IsOnSlot ? letterInputTileParent.transform : null);
        }
    }
}

3. 修正碰撞计数逻辑

统计碰撞的LetterTile数量,只有当所有Tile离开时才切换IsOnSlot状态:

private int _collisionCount;

private void OnCollisionEnter2D(Collision2D other)
{
    if (other.gameObject.CompareTag("MLetterTile"))
    {
        _collisionCount++;
        IsOnSlot = true;
    }
}

private void OnCollisionExit2D(Collision2D other)
{
    if (other.gameObject.CompareTag("MLetterTile"))
    {
        _collisionCount--;
        if (_collisionCount <= 0)
        {
            IsOnSlot = false;
            _collisionCount = 0; // 避免计数为负
        }
    }
}

4. 额外排查点

  • 检查LetterTile的gameObject.activeSelf是否为true,确保没有被意外禁用。
  • 查看LetterTile的transform.localScale,确认没有被缩放到0。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 04:17:51