玩家站在父化对象上缩放异常,解除父化后无法恢复如何解决?
解决SetParent导致玩家缩放异常的问题
核心解决方案
直接使用Transform.SetParent的重载方法,设置父物体时保持玩家的世界空间属性不变:
- 设置父物体时,调用
Player.transform.SetParent(transform, false);,第二个参数false表示不将玩家的局部变换转换为父物体的局部空间,而是保留世界空间的缩放、位置和旋转。 - 解除父化时直接设置
Player.transform.parent = null;即可,此时玩家的世界缩放会保持原本的状态。
问题根源
你遇到的缩放异常,是因为Unity默认设置父物体时(transform.parent = xxx等价于SetParent(xxx, true)),会将子物体的世界变换转换为相对于父物体的局部变换。如果父物体本身有非(1,1,1)的缩放,玩家的局部缩放会被强制调整,导致世界缩放偏离初始值;解除父化时,局部缩放会被转为世界缩放,但因为浮点精度问题,无法完全恢复到(1,1,1)。
修改后的代码
public class PlatformSideToSide : MonoBehaviour { public GameObject Player; public float moveAmount = 1.5f; public float speed = 5.0f; private Vector3 startPos; void Start() { startPos = transform.position; } void Update() { // 平台移动逻辑 Vector3 v = startPos; v.x += moveAmount * Mathf.Sin(Time.time * speed); transform.position = v; } private void OnTriggerEnter(Collider other) { if (other.gameObject == Player) { // 使用重载方法保持世界空间属性 Player.transform.SetParent(transform, false); } } private void OnTriggerExit(Collider other) { if (other.gameObject == Player) { Player.transform.parent = null; } } }
额外说明
如果你的平台本身需要缩放,或者有特殊需求必须转换局部空间,也可以在设置父物体前先保存玩家的世界缩放,解除父化后再强制赋值:
// 保存缩放的变量 private Vector3 _playerOriginalScale; private void OnTriggerEnter(Collider other) { if (other.gameObject == Player) { _playerOriginalScale = Player.transform.lossyScale; Player.transform.parent = transform; } } private void OnTriggerExit(Collider other) { if (other.gameObject == Player) { Player.transform.parent = null; // 强制恢复原始世界缩放 Player.transform.localScale = _playerOriginalScale; } }
不过这种方法不如直接用SetParent(false)可靠,因为lossyScale是只读的世界缩放,赋值localScale时如果父物体有缩放,可能还是会有偏差,优先推荐第一种方案。
内容的提问来源于stack exchange,提问作者dangoqut132
相关产品推荐
相关产品推荐

