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

Unity中ROS订阅回调Delegate Target为null导致回调未触发问题

问题:Unity中通过反射创建ROS订阅回调时Delegate Target为null导致回调不触发

我在Unity中使用ROS或ZMQ与设备通信,为实现无需重构代码即可适配两种通信方式,创建了接口类连接主代码与通信库。但订阅ROS话题时,回调函数从未被调用,排查发现即使创建Delegate时指定了this,其Target仍为null。


主类RobotCommand中创建订阅的代码

// ... (class RobotCommand)

try
{
    var defineSubscriberMethod = m_interface.GetType().GetMethod("DefineSubscriber");
    var genericMethod = defineSubscriberMethod.MakeGenericMethod(m_interface.TypeFloatArrayAlias);
    var delegateType = typeof(Action<>).MakeGenericType(m_interface.TypeFloatArrayAlias);
    
    var methodInfo = this.GetType().GetMethod(nameof(UpdateVirtualRobotJointsCallback),
        BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
    if (methodInfo == null)
        throw new Exception("Method 'UpdateVirtualRobotJointsCallback' not found.");

    Debug.Log($"Method Info: {methodInfo.Name} Target: {this.GetType().Name}");
    // 输出:Method Info: UpdateVirtualRobotJointsCallback Target: RobotCommand
    Delegate callbackDelegate = Delegate.CreateDelegate(delegateType, this, methodInfo);
    Debug.Log($"Delegate Target: {callbackDelegate.Target}, Method: {callbackDelegate.Method}");
    // 输出:Delegate Target: null, Method: Void UpdateVirtualRobotJointsCallback(RosMessageTypes.Std.Float32MultiArrayMsg)

    genericMethod.Invoke(m_interface, new object[]
    {
        Const.ROS_NAMESPACE + "robot_joint_values",
        callbackDelegate
    });
}
catch (Exception e)
{
    Debug.LogError($"Error invoking DefineSubscriber: {e.Message}");
}
}

public void UpdateVirtualRobotJointsCallback(Float32MultiArrayMsg msg)
{
    Debug.Log("called");
    StartCoroutine(m_controller.MoveRobot_Coroutine(m_interface.ToFloatArray(msg)));
}

接口类中的DefineSubscriber方法

public override void DefineSubscriber<T>(string topic, Action<T> callback)
{
    try
    {
        Debug.Log($"Delegate Callback: Target={callback.Target}, Method={callback.Method}");
        // 输出:Delegate Callback: Target=null, Method=Void UpdateVirtualRobotJointsCallback(RosMessageTypes.Std.Float32MultiArrayMsg)

        Type msgType = typeof(T);
        // _node 是 ROS 对象(ROSConnection.GetOrCreateInstance())
        var subscribeMethod = _node.GetType().GetMethod("Subscribe").MakeGenericMethod(msgType);
        subscribeMethod.Invoke(_node, new object[] { topic, callback });
        
        _subscriberList[topic] = (x => callback((T)x), msgType);
        Debug.Log($"Subscriber created for topic: {topic} with message type: {msgType.Name}");
    }
    catch (Exception e)
    {
        Debug.LogError($"Error while defining subscriber for topic {topic}: {e.Message}");
    }
}

正常工作的订阅创建参考代码

void Start()
{
    ROSConnection.GetOrCreateInstance().Subscribe<Float32MultiArrayMsg>(m_topicName, UpdateVirtualRobotJointsCallback);
}

// Update is called once per frame
void Update()
{
    
}

void UpdateVirtualRobotJointsCallback(Float32MultiArrayMsg msg)
{
    Debug.Log("called");
    StartCoroutine(xarmController.MoveRobot_Coroutine(new List<float>(msg.data)));
}

调试时确认Delegate的Target始终为null,推测这是回调未被调用的根本原因。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 14:59:56