Unity 2D中如何让父物体旋转时不带动子物体但继承其位置?
解决Unity 2D中行星旋转不影响飞船的几种方案
你遇到的核心问题是父子对象会继承父级的位置、旋转和缩放属性,所以行星旋转时飞船会跟着转。下面给你三个实用的解决思路,根据你的需求选择即可:
方案一:放弃父子关系,手动同步行星位置
直接在脚本里记录飞船相对于行星的偏移,当飞船进入范围后,每帧同步行星的位置,同时保持飞船的偏移量不变,这样既实现了随行星移动,又完全不受旋转影响。
修改后的脚本如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ParentPlayer : MonoBehaviour { [SerializeField] GameObject Player; [SerializeField] float Threshold; private CircleCollider2D ParentTrigger; private bool isTrackingPlanet = false; private Vector3 offsetToPlanet; // 记录飞船和行星的初始相对偏移 void Start() { ParentTrigger = GetComponents<CircleCollider2D>()[1]; ParentTrigger.isTrigger = true; ParentTrigger.radius = Threshold / transform.localScale.x; } void Update() { if (isTrackingPlanet) { // 让飞船保持相对于行星的初始位置,同步行星移动 Player.transform.position = transform.position + offsetToPlanet; } } private void OnTriggerEnter2D(Collider2D collider) { if (collider.gameObject == Player) { isTrackingPlanet = true; // 计算进入范围时飞船和行星的相对位置 offsetToPlanet = Player.transform.position - transform.position; } } private void OnTriggerExit2D(Collider2D collider) { if (collider.gameObject == Player) { isTrackingPlanet = false; } } void OnDrawGizmos() { Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, Threshold); } }
方案二:用中间空对象做“移动容器”
在行星下面挂一个空物体,让这个空物体只继承行星的位置,不继承旋转(确保空物体自身旋转始终为0,且行星的旋转脚本不影响它)。当飞船进入范围时,把飞船设为这个空物体的子物体,这样飞船只会跟着行星移动,不会被带着旋转。
步骤:
- 在行星对象下创建空物体,命名为
PlanetMoveContainer,设置它的旋转为(0,0,0)。 - 修改原脚本,把飞船的父级指向这个空物体:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class ParentPlayer : MonoBehaviour { [SerializeField] GameObject Player; [SerializeField] float Threshold; [SerializeField] Transform PlanetMoveContainer; // 拖拽空物体到这里 private CircleCollider2D ParentTrigger; void Start() { ParentTrigger = GetComponents<CircleCollider2D>()[1]; ParentTrigger.isTrigger = true; ParentTrigger.radius = Threshold / transform.localScale.x; } private void OnTriggerEnter2D(Collider2D collider) { if (collider.gameObject == Player) { // 飞船成为空物体的子级,只随行星移动,不受旋转影响 collider.gameObject.transform.SetParent(PlanetMoveContainer); } } private void OnTriggerExit2D(Collider2D collider) { if (collider.gameObject == Player) { collider.gameObject.transform.SetParent(null); } } void OnDrawGizmos() { Gizmos.color = Color.red; Gizmos.DrawWireSphere(transform.position, Threshold); } }
方案三:在飞船脚本中抵消父级旋转影响
如果必须把飞船直接设为行星的子物体,可以给飞船加一个脚本,每帧重置飞船的局部旋转,抵消行星旋转带来的影响。
给飞船挂载以下脚本:
using UnityEngine; public class CancelParentRotation : MonoBehaviour { private Quaternion initialLocalRot; private Transform parentTrans; void Start() { // 记录飞船初始的局部旋转 initialLocalRot = transform.localRotation; parentTrans = transform.parent; } void LateUpdate() { if (parentTrans != null) { // 强制重置局部旋转为初始值,抵消父级旋转 transform.localRotation = initialLocalRot; } } }
各方案优缺点:
- 方案一:逻辑简单,不需要额外对象,适合大多数场景;
- 方案二:保留父子结构,适合需要继承其他移动相关属性的情况;
- 方案三:适合必须用行星直接作为父级的特殊场景,但会有微小的性能开销(2D场景可忽略)。
内容的提问来源于stack exchange,提问作者CodingBeanz
相关产品推荐
相关产品推荐

