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

如何通过UniRx监听子GameObject添加并获取新增对象?

没问题,我来帮你搞定这个需求!你遇到的问题是UniRx的OnTransformChildrenChangedAsObservable()只返回Unit,没办法直接拿到新增的子物体,下面给你两种可行的方案,一种基于UniRx扩展,另一种是不用UniRx的传统Unity方法:

方案一:扩展UniRx的Observable,直接返回新增子物体

我们可以自己写一个扩展方法,基于原有的OnTransformChildrenChangedAsObservable(),通过对比子物体数量的变化来找出新增的对象。这样就能实现你想要的直接拿到GameObject的效果:

using UnityEngine;
using UniRx;
using System;

public static class TransformUniRxExtensions
{
    public static IObservable<GameObject> OnTransformChildAddedAsObservable(this Transform parentTransform)
    {
        // 记录初始的子物体数量
        int previousChildCount = parentTransform.childCount;
        
        return parentTransform.OnTransformChildrenChangedAsObservable()
            .Select(_ =>
            {
                int currentChildCount = parentTransform.childCount;
                // 只有当子物体数量增加时,才处理新增的对象
                if (currentChildCount > previousChildCount)
                {
                    // 新增的子物体是最后一个(因为SetParent会把它加到末尾)
                    GameObject addedChild = parentTransform.GetChild(currentChildCount - 1).gameObject;
                    previousChildCount = currentChildCount;
                    return addedChild;
                }
                // 如果是子物体被移除的情况,这里返回null,后续过滤掉
                return null;
            })
            // 过滤掉移除子物体时的null结果
            .Where(child => child != null);
    }
}

使用这个扩展方法就可以直接拿到新增的子物体了:

var parent = new GameObject("parent");
parent.transform.OnTransformChildAddedAsObservable()
    .Subscribe(g => { Debug.Log($"新增的子物体:{g.name}"); });

var child = new GameObject("child");
child.transform.SetParent(parent.transform);

方案二:不用UniRx,用Unity原生方法监听

如果你不想依赖UniRx,可以在父物体上挂载一个脚本,重写Unity原生的OnTransformChildrenChanged方法,通过对比前后的子物体集合来找出新增的对象:

using UnityEngine;
using System.Collections.Generic;

public class ChildAddedDetector : MonoBehaviour
{
    // 用HashSet来存储已有的子物体Transform,方便快速查找
    private HashSet<Transform> _existingChildren = new HashSet<Transform>();

    private void Awake()
    {
        // 初始化时记录所有已有的子物体
        foreach (Transform child in transform)
        {
            _existingChildren.Add(child);
        }
    }

    private void OnTransformChildrenChanged()
    {
        // 遍历当前所有子物体,找出新增的那个
        foreach (Transform child in transform)
        {
            if (!_existingChildren.Contains(child))
            {
                Debug.Log($"新增的子物体:{child.gameObject.name}");
                _existingChildren.Add(child);
            }
        }

        // 如果你还需要处理子物体被移除的情况,可以在这里添加逻辑:
        // 遍历_existingChildren,找出不在当前子物体列表中的项
    }
}

使用方法很简单:给你的parent GameObject挂上这个脚本,之后每次添加子物体时,就会自动打印新增的子物体名称了。

额外说明

  • 两种方案都支持批量添加子物体的情况(比如一次添加多个),会逐个检测出新增的对象。
  • 如果需要区分“添加”和“移除”操作,可以在逻辑中增加对数量减少的判断,或者对比集合找出被移除的对象。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 21:48:14