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

Unity 3D:如何持续测量固定与可移动卡尺间的距离

卡尺距离测量异常排查与解决

问题场景

使用两个立方体搭建卡尺测量装置:

  • 通过PI脚本在参与者前方实例化固定的底部卡尺和可移动的顶部卡尺
  • 通过CC脚本控制顶部卡尺上下移动,碰撞到底部卡尺时禁止向下移动
  • 给顶部卡尺挂载LiveDistanceBetweenCalipers脚本实时测量Y轴距离,但出现两个异常:
    1. 场景中绘制的绿色连线位置与顶部卡尺视觉位置不符
    2. 输出的距离数值和实际视觉距离不匹配

现有代码

1. PI脚本(卡尺实例化)

public void InstantiateCalipersAtDistance()
{
    if (headCamera != null)
    {
        float heightInMeters = participantHeightCm / 100f;
        float distance = heightInMeters; // Distance in front of the participant
        Vector3 headPosition = headCamera.transform.position; // Get the head camera position
        Vector3 forward = transform.forward;

        Vector3 baseCaliperPosition = headPosition + forward * distance;
        caliperSeparationDistance = Random.Range(0.05f, 0.25f); // Random distance between 0.05 and 0.25 meters

        baseCaliper = Instantiate(baseCaliperPrefab, baseCaliperPosition, Quaternion.identity);
        movingCaliper = Instantiate(movingCaliperPrefab, baseCaliperPosition + new Vector3(0, caliperSeparationDistance, 0), Quaternion.identity);
    }
    else
    {
        Debug.LogError("Head camera is not assigned.");
    }
}

2. CC脚本(顶部卡尺移动控制)

void Update()
{
    if (canMoveUp)
    {
        if (Input.GetKey(KeyCode.UpArrow))
        {
            transform.Translate(0, speed * Time.deltaTime, 0);
        }
    }
    if (canMoveDown)
    {
        if (Input.GetKey(KeyCode.DownArrow))
        {
            transform.Translate(0, -speed * Time.deltaTime, 0);
        }
    }
}

void OnCollisionEnter(Collision collision)
{
    if (collision.gameObject.name == "BaseCaliper(Clone)")
    {
        canMoveDown = false;
    }
}

void OnCollisionExit(Collision collision)
{
    if (collision.gameObject.name == "BaseCaliper(Clone)")
    {
        canMoveDown = true;
    }
}

3. 距离测量脚本

using UnityEngine;

public class LiveDistanceBetweenCalipers : MonoBehaviour
{
    [SerializeField] public GameObject obj; // Reference to the other caliper (base caliper)
    public float yDistanceBetweenObjects; // Variable to store the Y distance

    private void Update()
    {
        if (obj != null)
        {
            // Calculate the Y distance between this object (moving caliper) and the other object (base caliper)
            yDistanceBetweenObjects = Mathf.Abs(transform.position.y - obj.transform.position.y);
            // Print the Y distance to the console
            Debug.Log("Y Distance between calipers: " + yDistanceBetweenObjects);
            // Optionally, draw a line between the objects for visualization
            Debug.DrawLine(transform.position, obj.transform.position, Color.green);
        }
        else
        {
            Debug.LogWarning("Reference to the other caliper (base caliper) is missing.");
        }
    }
}

排查与解决方案

1. 预制体Pivot点偏移(最可能原因)

  • 问题本质:transform.position返回的是物体Pivot点的世界坐标,如果两个卡尺预制体的Pivot不在同一基准位置(比如一个在底部,一个在几何中心),计算出的Y差会和视觉距离不符,连线也会偏移。
  • 解决步骤:
    1. 打开底部和顶部卡尺的预制体
    2. 用Unity编辑器的Rect Tool(快捷键T),将两个卡尺的Pivot调整到同一基准(比如都设置在物体底部,确保测量的是垂直方向的实际视觉距离)
    3. 或直接在Inspector的Transform组件中手动修改Pivot值(比如底部基准的话,Pivot的Y值设为0)

2. 脚本挂载对象错误

  • 问题本质:如果LiveDistanceBetweenCalipers脚本挂载在卡尺的子物体上,transform.position获取的是子物体位置,而非卡尺根物体位置,导致连线和数值错误。
  • 解决步骤:
    1. 确认脚本挂载对象是卡尺的根GameObject
    2. 若必须挂载在子物体上,修改代码获取根物体位置:
      // 替换原位置计算逻辑
      Vector3 ownRootPosition = GetComponentInParent<Transform>().position;
      Vector3 targetRootPosition = obj.GetComponentInParent<Transform>().position;
      yDistanceBetweenObjects = Mathf.Abs(ownRootPosition.y - targetRootPosition.y);
      Debug.DrawLine(ownRootPosition, targetRootPosition, Color.green);
      

3. 手动引用赋值错误

  • 问题本质:手动在Inspector中拖入底部卡尺时,可能误拖了无关对象(比如父物体、其他克隆体),导致obj引用错误。
  • 解决步骤:
    去掉手动赋值,改为实例化时自动绑定引用,修改PI脚本的实例化代码:
    // 实例化后添加以下代码
    var distanceScript = movingCaliper.GetComponent<LiveDistanceBetweenCalipers>();
    if (distanceScript != null)
    {
        distanceScript.obj = baseCaliper;
    }
    

4. 碰撞体与模型位置不匹配

  • 问题本质:如果卡尺的碰撞体位置和视觉模型偏移,碰撞停止时的实际位置和视觉贴合位置有偏差,进而影响距离计算。
  • 解决步骤:
    1. 打开预制体,调整碰撞体的Position和Size,让它完全贴合视觉模型
    2. 可选:将OnCollisionEnter/Exit改为OnTriggerEnter/Exit(需勾选碰撞体的Is Trigger),避免物理碰撞带来的位置偏移

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 23:12:22