Unity拾取物体后透视拉伸 如何保持物体原有缩放比例
Unity 拾取功能物体透视拉伸问题修复
问题描述
拾取物体后转动视角时,持握的物体会随透视效果出现非预期拉伸变形,拾取前后效果如下:
- 拾取前(物体原始尺寸):

- 拾取后(物体变形效果):

核心诉求:拾取过程中维持物体缩放参数稳定,消除拉伸变形。
现有实现代码
PickupObject 拾取方法
public void PickupObject() { physicsObject = lookObject.GetComponentInChildren<PhysicsObjects>(); currentlyPickedUpObject = lookObject; pickupRB = currentlyPickedUpObject.GetComponent<Rigidbody>(); /* priorConstraints = pickupRB.constraints; // <--- NEW pickupRB.constraints = RigidbodyConstraints.FreezeAll; // <--- NEW*/ pickupRB.constraints = RigidbodyConstraints.FreezeRotation; physicsObject.playerInteractions = this; pickupRB.isKinematic = true; pickupRB.transform.parent = PickupParent.transform; // pickupRB.isKinematic = true; // StartCoroutine(physicsObject.PickUp()); }
Update 中持物/投掷/断开连接逻辑
if (currentlyPickedUpObject != null) { HoldingItemIcon.SetActive(true); InteractIcon.SetActive(false); CenterIcon.SetActive(false); currentDist = Vector3.Distance(PickupParent.position, pickupRB.position); currentSpeed = Mathf.SmoothStep(minSpeed, maxSpeed, currentDist / maxDistance); currentSpeed *= Time.fixedDeltaTime; pickupRB.transform.position = PickupParent.position; // pickupRB.transform.SetParent(PickupParent.transform); Vector3 direction = PickupParent.position - pickupRB.position; pickupRB.velocity = direction.normalized * currentSpeed; Vector3 camerDirection = mainCamera.transform.forward; // 投掷物体 if (Throw) { HoldingItemIcon.SetActive(false); InteractIcon.SetActive(false); pickupRB.constraints = RigidbodyConstraints.None; pickupRB.isKinematic = false; pickupRB.AddForce(camerDirection * 500); currentlyPickedUpObject = null; pickupRB.transform.parent = null; } Throw = false; } public void BreakConnection() { pickupRB.isKinematic = false; pickupRB.transform.parent = null; pickupRB.constraints = priorConstraints; // pickupRB.constraints = RigidbodyConstraints.None; currentlyPickedUpObject = null; lookObject = null; physicsObject.pickedUp = false; currentDist = 0; pickupRB.useGravity = true; }
参考截图
- 场景截图1:

- 场景截图2:

- 拾取状态下PickupParent的lossyScale参数:

问题根因
拉伸问题来自父物体PickupParent的缩放不是等比(1,1,1),且其上级父物体链存在非等比缩放。Unity中子物体的世界空间缩放为自身localScale与所有父物体lossyScale的乘积,只要父链存在x/y/z轴缩放值不一致的情况,子物体随父物体旋转时,不同轴向的缩放传递就会不匹配,叠加透视相机投影后就会出现明显的拉伸变形,提供的lossyScale截图可以直接验证这个问题。
修复方案
二选一即可:
- 方案1(推荐,改动最小无副作用):取消拾取物体与PickupParent的父子层级绑定,直接每帧同步物体的位置和旋转到PickupParent的坐标,完全规避父物体缩放传递问题:
- 删除
PickupObject()方法中的pickupRB.transform.parent = PickupParent.transform; - 删除投掷逻辑、
BreakConnection()方法中所有pickupRB.transform.parent = null;代码 - 在Update持物逻辑块中,原有设置position的代码后,添加旋转同步代码:
pickupRB.transform.rotation = PickupParent.rotation;
- 删除
- 方案2(保留父子层级):检查
PickupParent以及它所有上级父物体(包括主相机、相机挂载的父节点)的Transform缩放值,将所有轴向缩放统一设为1,原本靠缩放实现的持物偏移效果,改为调整PickupParent的Position值实现。
额外优化提示:当前代码同时用了直接修改transform.position和给刚体赋值velocity的逻辑,持物阶段刚体为isKinematic状态时,用Rigidbody.MovePosition()和Rigidbody.MoveRotation()同步坐标,物理效果会更平滑,不会出现位置抖动。
内容的提问来源于stack exchange,提问作者Okashi
相关产品推荐
相关产品推荐

