Unity ARFoundation多图像跟踪Canvas仅显示一次问题求助
问题分析与修复方案
核心问题
- 延迟调用冲突:
Invoke的0.5秒延迟会导致状态判断滞后,比如图像刚被跟踪就丢失时,可能先后触发EnableMe和DisableMe,最终Canvas状态不符合预期。 - 无效的
trackedImage重置:DisableMe中重置的trackedImage是foreach循环内的局部变量,而非类的成员变量,对后续跟踪判断完全没有影响。 - 缺少跟踪状态记录:没有记录当前正在跟踪的图像标识,无法区分新跟踪事件和重复触发,导致Canvas无法反复显示。
修复代码
首先在类中添加成员变量,用于记录跟踪状态和管理延迟操作:
// 记录当前正在跟踪的椅子图像名称 private string currentTrackedChairName; // 管理延迟调用的协程,避免状态冲突 private Coroutine enableCoroutine; private Coroutine disableCoroutine;
然后修改核心逻辑方法,替换Invoke为可控性更强的协程,并增加状态判断:
private void UpdateTrackedImages(IEnumerable<ARTrackedImage> trackedImages) { bool hasTrackedChair = false; string trackedChairName = null; // 遍历找到当前正在跟踪的目标椅子 foreach (var trackedImage in trackedImages) { if (Chairs.Contains(trackedImage.referenceImage.name) && trackedImage.trackingState == TrackingState.Tracking) { hasTrackedChair = true; trackedChairName = trackedImage.referenceImage.name; break; // 找到一个跟踪目标即可,避免多图像冲突 } } // 根据跟踪状态处理Canvas显示/隐藏 if (hasTrackedChair) { // 仅当跟踪的是新图像,或之前无跟踪时才触发显示 if (currentTrackedChairName != trackedChairName) { // 取消可能存在的隐藏延迟 if (disableCoroutine != null) { StopCoroutine(disableCoroutine); disableCoroutine = null; } // 启动显示延迟协程 enableCoroutine = StartCoroutine(EnableCanvasAfterDelay(0.5f, trackedChairName)); } } else { // 仅当之前有跟踪目标时才触发隐藏 if (!string.IsNullOrEmpty(currentTrackedChairName)) { // 取消可能存在的显示延迟 if (enableCoroutine != null) { StopCoroutine(enableCoroutine); enableCoroutine = null; } // 启动隐藏延迟协程 disableCoroutine = StartCoroutine(DisableCanvasAfterDelay(0.5f)); } } } private IEnumerator EnableCanvasAfterDelay(float delay, string chairName) { yield return new WaitForSeconds(delay); canvas.enabled = true; currentTrackedChairName = chairName; // 根据当前跟踪的图像更新按钮信息 UpdateButtonInfo(chairName); } private IEnumerator DisableCanvasAfterDelay(float delay) { yield return new WaitForSeconds(delay); canvas.enabled = false; currentTrackedChairName = null; } // 根据图像名称动态更新按钮的文本和点击事件 private void UpdateButtonInfo(string chairName) { switch(chairName) { case "Chair1": button.text = "查看椅子1详情"; button.onClick.RemoveAllListeners(); button.onClick.AddListener(ShowChair1Info); break; case "Chair2": button.text = "查看椅子2详情"; button.onClick.RemoveAllListeners(); button.onClick.AddListener(ShowChair2Info); break; // 其他椅子的逻辑补充 } } // 示例:椅子1详情展示逻辑 private void ShowChair1Info() { // 自定义逻辑 } // 示例:椅子2详情展示逻辑 private void ShowChair2Info() { // 自定义逻辑 }
关键改进点
- 协程替代Invoke:可以随时取消未执行的延迟操作,避免状态冲突,比如图像刚触发显示就丢失时,能直接切换到隐藏逻辑。
- 跟踪状态记录:通过
currentTrackedChairName记录当前跟踪的图像,确保只有状态变化时才更新Canvas,支持反复显示不同图像对应的Canvas。 - 按钮动态更新:在Canvas显示时,根据跟踪的图像名称同步更新按钮的文本和点击事件,满足“按钮接收不同信息”的需求。
- 修复无效重置:不再操作局部变量
trackedImage,改用成员变量控制跟踪状态,彻底解决重置无效的问题。
内容的提问来源于stack exchange,提问作者Brahe
相关产品推荐
相关产品推荐

