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

2D无人机游戏中飞行键重置旋转后松开按键旋转复原且速度不受控的问题求助

2D无人机游戏中飞行键重置旋转后松开按键旋转复原且速度不受控的问题求助

看起来你遇到了两个核心的头疼问题:按下飞行键时无人机能暂时重置旋转,但一松开就又回到之前的旋转状态,而且还会继续沿着之前的下落方向飘,完全不受控。我来帮你一步步拆解解决~

问题根源分析

  1. 旋转复原的原因:你只在flyInput为true时通过transform.rotation强行设置旋转,但Rigidbody2D的旋转其实受物理引擎控制——之前碰撞产生的**旋转角速度(angularVelocity)**还存在,松开飞行键后你不再强制修正旋转,物理引擎就会让刚体继续按照原来的角速度转回去。
  2. 速度不受控的原因:你当前的Fly()方法只是给刚体加一个向上的冲量,但刚体原来的运动速度还在,两者叠加后就会出现“明明按了飞行键,却还是往之前的方向飘”的情况。

针对性解决方案

我会基于你的代码直接修改,精准解决这两个问题:

1. 修复旋转问题:停止旋转角速度+锁定旋转(可选)

当按下飞行键时,不仅要重置旋转,还要清空刚体的旋转角速度,让它彻底停止旋转;如果希望飞行过程中保持水平不旋转,可以直接锁定刚体的旋转属性。

2. 修复速度问题:重置刚体速度到飞行方向

把原来的“添加向上冲量”改成“直接设置刚体速度”,这样就能覆盖掉之前的下落速度,让无人机完全按照飞行指令运动。

修改后的完整代码

using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
    [SerializeField] private InputReader inputReader;
    private GroundDetection groundDetection;
    private BatterySystem batterySystem;
    private Rigidbody2D rb;
    private Quaternion startingRotation;

    [SerializeField] private float moveSpeed = 5;
    [SerializeField] private float flyVelocity = 5;
    private Vector2 moveInput;
    public bool flyInput { get; private set; }

    void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    void Start()
    {
        batterySystem = GetComponent<BatterySystem>();
        groundDetection = GetComponentInChildren<GroundDetection>();
        // 存储初始旋转(这里用Quaternion.identity代表无旋转,和你原来的逻辑一致)
        startingRotation = Quaternion.identity;
    }

    void OnEnable()
    {
        inputReader.MoveEvent += HandleMove;
        inputReader.FlyEvent += HandleFly;
    }

    void OnDisable()
    {
        inputReader.MoveEvent -= HandleMove;
        inputReader.FlyEvent -= HandleFly;
    }

    // 刚体相关操作统一放到FixedUpdate,和物理引擎更新频率同步
    private void FixedUpdate()
    {
        Move();
        Fly();
    }

    private void HandleMove(Vector2 _moveInput)
    {
        moveInput = _moveInput;
    }

    private void HandleFly(bool _flyInput)
    {
        flyInput = _flyInput;
    }

    private void Move()
    {
        if (groundDetection.isGrounded)
        {
            // 地面移动:用Rigidbody2D的velocity控制,避免和物理引擎冲突
            rb.velocity = new Vector2(moveInput.x * moveSpeed, rb.velocity.y);
        }
        else if (!flyInput)
        {
            // 非飞行状态下的空中移动(可选,根据你的需求调整)
            rb.velocity = new Vector2(moveInput.x * moveSpeed, rb.velocity.y);
        }
    }

    private void Fly()
    {
        if (flyInput && batterySystem.currentBattery > 0)
        {
            // 1. 重置旋转到初始状态
            transform.rotation = startingRotation;
            // 2. 清空旋转角速度,彻底停止旋转,避免弹回之前的旋转状态
            rb.angularVelocity = 0f;
            // 3. 锁定旋转,让飞行过程中始终保持水平(不需要的话可以注释掉)
            rb.freezeRotation = true;

            // 4. 重置刚体速度:覆盖原有速度,只保留飞行方向+水平移动输入
            Vector2 targetFlyVelocity = new Vector2(moveInput.x * moveSpeed, flyVelocity);
            rb.velocity = targetFlyVelocity;
        }
        else
        {
            // 松开飞行键后,解锁旋转(如果之前锁定了)
            rb.freezeRotation = false;
        }
    }
}

关键修改点说明

  • 把Move()移到FixedUpdate:刚体相关的操作都应该在FixedUpdate里执行,和物理引擎的更新频率同步,避免卡顿或逻辑冲突。
  • 替换transform.Translate为rb.velocity:直接修改transform位置会绕过物理引擎,容易出现穿模、不受重力等异常,用velocity控制移动才是Rigidbody2D的正确用法。
  • 新增rb.angularVelocity = 0f;:清空旋转角速度,让无人机彻底停止旋转,不会再“弹回”之前的旋转状态。
  • 用rb.velocity替代AddForce:直接设置速度可以完全覆盖之前的运动状态,让无人机立刻响应飞行指令,不会叠加旧速度。
  • 可选的rb.freezeRotation:如果希望飞行时无人机始终保持水平,就保留这个设置;如果需要飞行中允许少量旋转,可以注释掉这行。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 10:33:03