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

如何设置GameObject父对象且不改变子对象的缩放比例

解决Unity中SetParent导致子物体缩放/旋转失真的问题

问题根源

当父物体存在非均匀缩放(x/y/z缩放数值不一致)+ 旋转时,父物体的变换矩阵会产生剪切变换。子物体的局部变换会与这个带剪切的矩阵相乘,导致子物体顶点被扭曲,最终表现为网格失真。你之前用空物体当中间层的思路是对的,但没处理好空物体和子物体的变换同步,才会在父物体旋转时出问题。

正确解决方案:用中间空物体隔离变换

创建一个空物体作为“变换隔离层”,承接父物体的变换,同时让子物体只继承该空物体的“干净”局部变换(无缩放、无旋转、无偏移),具体代码如下:

// 1. 记录子物体当前的世界变换状态(位置、旋转、缩放)
Vector3 originalWorldPos = childObject.transform.position;
Quaternion originalWorldRot = childObject.transform.rotation;
Vector3 originalWorldScale = childObject.transform.lossyScale;

// 2. 创建中间空物体并设置父节点
var transformWrapper = new GameObject("ChildTransformWrapper");
transformWrapper.transform.SetParent(parentObject.transform);

// 3. 重置空物体的局部变换,确保它只继承父物体的世界变换,自身无额外偏移/旋转/缩放
transformWrapper.transform.localPosition = Vector3.zero;
transformWrapper.transform.localRotation = Quaternion.identity;
transformWrapper.transform.localScale = Vector3.one;

// 4. 将子物体挂载到空物体下,并还原其世界变换状态
childObject.transform.SetParent(transformWrapper.transform);
childObject.transform.position = originalWorldPos;
childObject.transform.rotation = originalWorldRot;
// 计算子物体相对于空物体的局部缩放(抵消空物体继承的父物体缩放)
childObject.transform.localScale = Vector3.Scale(originalWorldScale, new Vector3(1/transformWrapper.transform.lossyScale.x, 1/transformWrapper.transform.lossyScale.y, 1/transformWrapper.transform.lossyScale.z));

为什么这样有效?

  • 空物体的局部变换是完全“干净”的(缩放1、旋转0、偏移0),它会继承父物体的世界变换,但不会向子物体传递父物体的非均匀缩放和旋转带来的剪切矩阵。
  • 还原子物体的世界变换后,Unity会自动计算子物体相对于空物体的局部变换,避免了父物体变换对其产生的扭曲。

额外提示

  • 如果你不需要子物体随父物体的缩放/旋转变化,直接把空物体的localScale和localRotation锁死为(1,1,1)和无旋转即可。
  • 避免在父物体上使用非均匀缩放,这是Unity中很多变换问题的根源,如果必须用,尽量用这种中间层隔离的方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 15:48:30