Unity接收数据但未更新场景的原因与解决方案(实操可解决)

问题回顾:在摄像头手势识别项目中,我使用 UDP 协议将 21 个关键点的三维坐标实时发送给 Unity,用于驱动场景中的手部骨架模型。然而在实际运行中,Unity 虽然成功接收到了数据,但所有节点对应的小球始终固定在初始位置,未能按照接收数据更新场景,导致虚拟手无法动起来。

Unity 子线程禁止修改 Transform

❗ 问题描述

在 Unity 中,尝试在子线程中执行以下代码:

handJoints[i].localPosition = pos;

会触发错误:

localPosition can only be set from the main thread.

这是因为 UnityEngine 的大多数 API(如 Transform、Renderer、Camera 等)不是线程安全的,只能在主线程中访问。


✅ 正确做法:将操作调度到主线程中执行

我们应当在子线程中只处理数据接收,再通过主线程去执行位置设置。


📌 使用 MainThreadDispatcher 工具

第一步:新建 MainThreadDispatcher.cs 脚本

using System;
using System.Collections.Generic;
using UnityEngine;

public class MainThreadDispatcher : MonoBehaviour
{
    private static readonly Queue<Action> actions = new Queue<Action>();

    public static void Enqueue(Action action)
    {
        lock (actions)
        {
            actions.Enqueue(action);
        }
    }

    void Update()
    {
        lock (actions)
        {
            while (actions.Count > 0)
            {
                actions.Dequeue()?.Invoke();
            }
        }
    }
}

第二步:添加到场景

将该脚本挂载到场景中任意一个 GameObject 上,建议创建一个空物体,命名为 MainThreadDispatcherHost 并挂载此脚本。


第三步:在 HandReceiver.cs 中替代原始写法

将原本在子线程中执行的代码:

handJoints[i].localPosition = pos;

改写为主线程调度方式:

int index = i;
Vector3 capturedPos = pos;

MainThreadDispatcher.Enqueue(() =>
{
    handJoints[index].localPosition = capturedPos;
});

✅ 最终效果

  • UDP 接收仍然在后台子线程处理;
  • 所有对 Transform 的修改都由 Unity 主线程安全完成;
  • 报错问题消失,逻辑清晰、稳定运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值