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

获取Transform子对象时跳过每隔一个子对象的问题

解决Unity中收集子对象的子对象时跳过元素的问题

嘿,我来帮你搞定这个头疼的问题!你遇到的“每隔一个子对象就被跳过”的情况,几乎可以肯定是因为遍历过程中修改了原对象的子对象集合——Unity的Transform子对象列表是动态的,当你把Tile从Segment下移走时,原Segment的childCount会立刻减少,直接导致遍历的索引错位,跳过了下一个元素。

问题根源分析

假设你原来的代码是类似这样的(直接在遍历中修改父对象):

// 错误示例:遍历中直接修改父对象,导致索引错位
Transform whole = wholeGameObject.transform;
Transform target = targetGameObject.transform;

for (int i = 0; i < whole.childCount; i++)
{
    Transform segment = whole.GetChild(i);
    for (int j = 0; j < segment.childCount; j++)
    {
        Transform tile = segment.GetChild(j);
        tile.SetParent(target); // 这里移走Tile后,segment的子对象数减1
    }
}

比如某个Segment下有4个Tile:

  • j=0时,移走第1个Tile,segment.childCount变成3
  • j自增到1,此时segment.GetChild(1)对应的是原来的第3个Tile,直接跳过了原来的第2个

正确的解决方案

核心思路是先把所有Tile一次性收集到临时集合里,再统一修改父对象,这样遍历原集合时不会因为元素被移走而出现索引问题,而且完全不用递归,两层循环就能搞定:

using System.Collections.Generic;
using UnityEngine;

public class TileCollector : MonoBehaviour
{
    public GameObject wholeGameObject; // 你的Whole对象
    public GameObject targetGameObject; // 要把Tile移到的目标对象

    public void CollectAndMoveTiles()
    {
        if (wholeGameObject == null || targetGameObject == null)
        {
            Debug.LogError("Whole或Target对象未赋值!");
            return;
        }

        Transform wholeTransform = wholeGameObject.transform;
        List<Transform> allTiles = new List<Transform>();

        // 第一层:遍历所有Segment
        for (int i = 0; i < wholeTransform.childCount; i++)
        {
            Transform segment = wholeTransform.GetChild(i);
            // 先把当前Segment的子对象数量存下来,避免遍历中意外变化(虽然这里只是收集,不会改,但更稳妥)
            int tileCount = segment.childCount;
            // 第二层:遍历当前Segment下的所有Tile,加入临时集合
            for (int j = 0; j < tileCount; j++)
            {
                Transform tile = segment.GetChild(j);
                allTiles.Add(tile);
            }
        }

        // 统一修改所有Tile的父对象
        Transform targetTransform = targetGameObject.transform;
        foreach (Transform tile in allTiles)
        {
            // 如果需要保持Tile的局部坐标不变,用第二个参数为false的重载
            tile.SetParent(targetTransform, false);
            // 如果要让Tile继承目标对象的坐标空间,用tile.SetParent(targetTransform);
        }

        Debug.Log($"成功收集并移动了{allTiles.Count}个Tile!");
    }
}

额外提示

  • 如果你的Segment或Tile有特定的标签,可以在收集时加个判断,比如if (tile.CompareTag("Tile")),避免收集到其他无关对象
  • 用List<Transform>而不是直接遍历修改,是因为List是静态集合,不会因为原对象的变化而改变,遍历起来完全安全

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:07:16