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

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,且行星的旋转脚本不影响它)。当飞船进入范围时,把飞船设为这个空物体的子物体,这样飞船只会跟着行星移动,不会被带着旋转。

步骤:

  1. 在行星对象下创建空物体,命名为PlanetMoveContainer,设置它的旋转为(0,0,0)。
  2. 修改原脚本,把飞船的父级指向这个空物体:
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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 11:35:22