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

基于Vuforia/Unity实现条码扫描动态模型叠加的问题排查

问题分析

你的核心问题在于错误依赖InstanceData是否为null来判断条码是否在视野内。Vuforia的BarcodeBehaviour中,InstanceData不会在条码移出视野后立刻置空,而是会保留上一次扫描的数据,导致你的else if分支永远不会触发,模型也就不会隐藏。

解决方案

改用TrackableBehaviour(BarcodeBehaviour的父类)的跟踪状态来判断条码是否被有效识别/跟踪,这是Vuforia官方推荐的判断方式。同时优化模型切换逻辑,确保扫描新条码时自动隐藏旧模型。

修改后的完整脚本

using UnityEngine;
using Vuforia;
using TMPro;

public class SimpleBarcodeScanner : MonoBehaviour
{
    public TextMeshProUGUI barcodeAsText;
    private BarcodeBehaviour _barcodeBehaviour;
    public DictionarySerializer dictionarySerializer;
    private GameObject _activeModel;

    void Start()
    {
        _barcodeBehaviour = GetComponent<BarcodeBehaviour>();
        _activeModel = null;
        
        // 注册跟踪状态变化事件,替代Update轮询(更高效)
        _barcodeBehaviour.OnTrackableStatusChanged += OnBarcodeTrackableStatusChanged;
    }

    // 使用事件监听处理跟踪状态变化(推荐,性能更好)
    private void OnBarcodeTrackableStatusChanged(TrackableBehaviour.Status previousStatus, TrackableBehaviour.Status newStatus)
    {
        switch (newStatus)
        {
            case TrackableBehaviour.Status.TRACKED:
            case TrackableBehaviour.Status.EXTENDED_TRACKED:
                HandleBarcodeDetected();
                break;
            case TrackableBehaviour.Status.NO_POSE:
            case TrackableBehaviour.Status.NOT_FOUND:
                HandleBarcodeLost();
                break;
        }
    }

    // 兼容旧版本Vuforia的Update轮询方式(可选)
    // void Update()
    // {
    //     if (_barcodeBehaviour == null) return;
    //
    //     var status = _barcodeBehaviour.CurrentStatus;
    //     if (status == TrackableBehaviour.Status.TRACKED || status == TrackableBehaviour.Status.EXTENDED_TRACKED)
    //     {
    //         HandleBarcodeDetected();
    //     }
    //     else
    //     {
    //         HandleBarcodeLost();
    //     }
    // }

    private void HandleBarcodeDetected()
    {
        if (_barcodeBehaviour.InstanceData == null) return;
        
        string barcodeText = _barcodeBehaviour.InstanceData.Text;
        barcodeAsText.text = barcodeText;
        Debug.Log($"Scanned Barcode ID: {barcodeText}");

        if (dictionarySerializer.GetObjectsDictionary() == null || !dictionarySerializer.GetObjectsDictionary().ContainsKey(barcodeText))
        {
            Debug.LogWarning($"No model mapped to barcode: {barcodeText}");
            return;
        }

        GameObject targetModel = dictionarySerializer.GetObjectsDictionary()[barcodeText];
        
        // 切换模型:如果当前有激活的模型且不是目标模型,先隐藏它
        if (_activeModel != null && _activeModel != targetModel)
        {
            _activeModel.SetActive(false);
        }
        
        // 激活目标模型
        targetModel.SetActive(true);
        _activeModel = targetModel;
    }

    private void HandleBarcodeLost()
    {
        Debug.Log("Barcode lost from view");
        if (_activeModel != null)
        {
            _activeModel.SetActive(false);
            _activeModel = null;
        }
        barcodeAsText.text = ""; // 可选:清空显示的条码文本
    }

    void OnDestroy()
    {
        // 移除事件监听,避免内存泄漏
        if (_barcodeBehaviour != null)
        {
            _barcodeBehaviour.OnTrackableStatusChanged -= OnBarcodeTrackableStatusChanged;
        }
    }
}

关键修改点说明

  1. 跟踪状态判断:用TrackableBehaviour.Status的枚举值替代InstanceData是否为空,准确识别条码状态:
    • TRACKED/EXTENDED_TRACKED:条码在视野内且被稳定跟踪
    • NO_POSE/NOT_FOUND:条码移出视野或无法识别
  2. 模型切换优化:扫描新条码时自动隐藏旧模型,实现无缝切换
  3. 事件监听替代Update轮询:使用OnTrackableStatusChanged事件代替每帧轮询,提升性能(也保留了Update方式作为兼容选项)
  4. 内存泄漏防护:在脚本销毁时移除事件监听

额外注意事项

  • 确保所有3D模型初始状态为非激活状态(SetActive(false)),避免一开始就显示
  • 模型的位置应该绑定到条码跟踪对象(即挂载BarcodeBehaviour的GameObject),这样模型才能跟随条码位置叠加显示
  • 检查DictionarySerializer返回的字典是否正确映射了条码ID和模型对象

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 06:53:11