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

AR多点测量APP故障排查:无法连续测量需重置场景

AR测量APP无限测量功能修复方案

核心问题分析

  • 原代码依赖固定长度的tapePoints数组,仅支持两个测量点,无法扩展新的测量线
  • currentTapePoint变量在达到2后会被强制重置为0,阻断了连续测量流程
  • 单个LineRenderer只能渲染一条线段,无法同时显示多条测量结果
  • 距离文本和浮动文本组件绑定单一实例,无法对应多条测量线的信息展示

具体修改方案

1. 重构数据结构,支持多组测量数据

替换原有的固定数组和单一组件定义,改用动态集合存储每组测量的元素:

// 删除原有的tapePoints、line定义,替换为以下内容
public GameObject tapePointPrefab; // 在Inspector中拖拽你的测量点预制体
public LineRenderer lineRendererPrefab; // 在Inspector中拖拽你的线段预制体
public GameObject floatingDistancePrefab; // 在Inspector中拖拽浮动文本预制体

private List<LineRenderer> allLines = new List<LineRenderer>();
private List<GameObject> allFloatingTexts = new List<GameObject>();

private int currentMeasureStage = 0; // 0: 等待选起点, 1: 等待选终点
private Vector3 currentStartPoint;
private LineRenderer previewLine; // 实时预览用的临时线段

2. 修改触摸逻辑,支持连续测量

去掉currentTapePoint的数值限制,改为完成一组测量后自动开启下一组:

// 修改Update方法中的触摸处理部分
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began)
{
    if (placementEnabled)
    {
        Vector3 hitPos = hits[0].pose.position;
        if (currentMeasureStage == 0)
        {
            // 放置测量起点
            currentStartPoint = hitPos;
            SpawnTapePoint(hitPos);
            currentMeasureStage = 1;
        }
        else if (currentMeasureStage == 1)
        {
            // 放置测量终点,完成当前组测量
            SpawnTapePoint(hitPos);
            SpawnNewLine(currentStartPoint, hitPos);
            SpawnFloatingText(currentStartPoint, hitPos);
            currentMeasureStage = 0; // 重置状态,准备下一组测量
        }
        placementEnabled = false;
    }
}

3. 新增实例化预制体的方法

添加动态生成测量点、线段、浮动文本的方法,避免复用旧组件冲突:

private void SpawnTapePoint(Vector3 position)
{
    GameObject point = Instantiate(tapePointPrefab, position, Quaternion.identity);
    point.transform.parent = transform; // 将测量点归到管理器对象下,方便统一管理
    point.tag = "TapePoint"; // 给测量点加标签,方便后续批量清理
}

private void SpawnNewLine(Vector3 start, Vector3 end)
{
    LineRenderer newLine = Instantiate(lineRendererPrefab, transform.position, Quaternion.identity);
    newLine.transform.parent = transform;
    newLine.SetPosition(0, start);
    newLine.SetPosition(1, end);
    allLines.Add(newLine);
}

private void SpawnFloatingText(Vector3 start, Vector3 end)
{
    GameObject textObj = Instantiate(floatingDistancePrefab, Vector3.Lerp(start, end, 0.5f), Quaternion.identity);
    textObj.transform.parent = transform;
    TMP_Text textComp = textObj.GetComponent<TMP_Text>();
    
    float distance = Vector3.Distance(start, end);
    float convertedDistance = ConvertDistance(distance);
    textComp.text = convertedDistance.ToString("#.##") + currentUnit;
    
    // 让文本始终朝向相机
    textObj.transform.rotation = Quaternion.LookRotation(Camera.main.transform.forward, Camera.main.transform.up);
    allFloatingTexts.Add(textObj);
}

// 抽离单位转换逻辑,提升复用性
private float ConvertDistance(float rawDistance)
{
    switch (currentUnit)
    {
        case Unit.m: return rawDistance;
        case Unit.cm: return rawDistance * 100;
        case Unit.i: return rawDistance / 0.0254f;
        case Unit.f: return rawDistance * 3.2808f;
        default: return rawDistance;
    }
}

4. 实现实时测量预览

在选择起点后,实时显示未完成的测量线和距离:

// 在Update方法中添加实时预览逻辑
if (currentMeasureStage == 1 && hits.Count > 0)
{
    // 创建或更新预览线
    if (previewLine == null)
    {
        previewLine = Instantiate(lineRendererPrefab, transform.position, Quaternion.identity);
        previewLine.transform.parent = transform;
        previewLine.material.color = Color.yellow; // 用不同颜色区分已完成的线
    }
    previewLine.SetPosition(0, currentStartPoint);
    previewLine.SetPosition(1, hits[0].pose.position);
    
    // 更新实时距离文本
    float tempDistance = Vector3.Distance(currentStartPoint, hits[0].pose.position);
    float converted = ConvertDistance(tempDistance);
    distanceText.text = converted.ToString("#.##") + currentUnit;
}
else
{
    // 隐藏并销毁预览线
    if (previewLine != null)
    {
        Destroy(previewLine);
        previewLine = null;
    }
}

5. 移除强制重置限制

删除原代码中阻断连续测量的强制重置逻辑:

// 修改原有的else if分支
else if (hits.Count == 0)
{
    reticle.SetActive(false);
    // 移除原有的 currentTapePoint = 0; 这行代码
}

6. 新增全局重置功能(可选)

添加按钮调用的方法,一键清空所有测量结果:

public void ResetAllMeasurements()
{
    // 销毁所有线段
    foreach (var line in allLines)
    {
        Destroy(line);
    }
    // 销毁所有浮动文本
    foreach (var text in allFloatingTexts)
    {
        Destroy(text);
    }
    // 销毁所有测量点
    foreach (Transform child in transform)
    {
        if (child.gameObject.CompareTag("TapePoint"))
        {
            Destroy(child.gameObject);
        }
    }
    
    // 清空集合并重置状态
    allLines.Clear();
    allFloatingTexts.Clear();
    currentMeasureStage = 0;
    distanceText.text = "0.00" + currentUnit;
}

关键修改说明

  • 用动态集合替代固定数组,实现无限测量的扩展性
  • 把测量流程拆分为「选起点→选终点→完成一组→开启下一组」,支持连续操作
  • 通过预制体实例化创建新的测量元素,避免复用旧组件导致的冲突
  • 抽离重复逻辑(如单位转换),提升代码可维护性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 08:47:44