unity动态将3d标牌UI加载到模型子物体下,UI变形问题

//1、直接生成模型
GameObject prefab = GameObject.Instantiate(modeinfo, SelectedModel.transform);
//2、先生成在世界下,再设置为子物体
prefab.transform.SetParent(currentlySelectedModel.transform); //同样SetParent方法默认下也是受父物体影响

该方法是将World Space 模式下的ui生成在 SelectedModel 模型下,即将ui作为子物体。此时ui的缩放值会受其父物体的缩放值的影响,故导致其变形。

以上两种办法都会导致ui变形。

解决方案:

// 需要补偿父物体的变换影响
private void LoadModeInfo()
{
   
    // 先计算补偿变换
    Vector3 parentScale = currentlySelectedModel.transform.lossyScale;
    Vector3 compensationScale = new Vector3(
        1f/parentScale.x, 
        1f/parentScale.y, 
        1f/parentScale.z
    ) * 0.1f;
    
    GameObject prefab = GameObject.Instantiate(modeinfo);
    prefab.transform.SetParent(currentlySelectedModel.transform, false); // false表示不立即应用父物体变换
    
    // 应用补偿缩放
    prefab.transform.localScale = compensationScale;
    //设置3d标牌位于人物中心0.55高度
    prefab.transform.localPosition = new Vector3(0, 0.55f, 0);
    
    Canvas canvas = prefab.GetComponent<Canvas>();
    canvas.worldCamera = Camera.main;

}

原理:

补偿计算原理解释
1. 目的
补偿计算是为了抵消父物体 scale 对子物体造成的变形影响,保持子物体在视觉上的正常大小。
2. 计算过程

  • 获取父物体的世界缩放
  Vector3 parentScale = currentlySelectedModel.transform.lossyScale;

lossyScale 返回物体在世界空间中的实际缩放值,包含了所有父级的缩放影响。

  • 计算补偿因子:
  Vector3 compensationScale = new Vector3(
      1f/parentScale.x, 
      1f/parentScale.y, 
      1f/parentScale.z
  ) * 0.1f;

分解为两步:
1、1f/parentScale - 计算每个轴的逆缩放因子,用于完全抵消父物体的缩放影响
2、* 0.1f - 应用目标缩放值(0.1倍标准大小)

3. 工作原理
当一个物体成为子物体时,它的最终显示大小 = localScale × parent.lossyScale

  • 如果不进行补偿,子物体会随父物体缩放而变形
  • 通过应用 1/parentScale 的补偿因子,可以抵消父物体的影响
  • 最终结果:子物体保持固定大小,不受父物体缩放影响

4. 示例
假设父物体 scale 为 (2, 2, 2):

  • 无补偿时子物体实际大小:(1, 1, 1) × (2, 2, 2) = (2, 2, 2) → 放大2倍
  • 应用补偿后:(0.05, 0.05, 0.05) × (2, 2, 2) = (0.1, 0.1, 0.1) → 保持0.1倍标准大小
posted on 2025-11-21 16:36  juaa  阅读(0)  评论(0)    收藏  举报