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

Unity中如何屏蔽陀螺仪Y轴运动,仅读取Z轴倾斜输入?

仅读取手机Z轴倾斜输入、忽略Y轴转动的实现方案

核心思路是从设备姿态数据中提取仅对应手机左右倾斜的分量,完全过滤掉绕Y轴转动(手机转向)带来的干扰,用这个分量单独控制物体绕Z轴旋转——这和《Traffic Racer》《Traffic Rider》的陀螺仪逻辑本质一致,只是把移动换成旋转。

通用原理说明

手机姿态数据通常用欧拉角或四元数表示,你需要明确区分两个关键分量:

  • Roll(绕X轴倾斜):对应手机左右倾斜(比如抬起手机左侧/右侧),这是你需要的控制输入
  • Yaw(绕Y轴转动):对应手机左右转向(比如拿着手机横向转动),这是需要忽略的干扰

不同平台的坐标系定义略有差异,需真机测试确认轴映射,但核心逻辑一致:只取Roll分量驱动物体旋转。

各平台实现示例

Unity 实现

使用陀螺仪融合后的姿态数据,提取Roll值并控制物体旋转:

public float rotationSpeed = 2f;
private float initialRoll;

void Start()
{
    Input.gyro.enabled = true;
    // 记录初始Roll值,消除初始姿态影响
    Quaternion initialAttitude = Input.gyro.attitude;
    Vector3 initialEuler = initialAttitude.eulerAngles;
    initialRoll = (initialEuler.x > 180) ? initialEuler.x - 360 : initialEuler.x;
}

void Update()
{
    Quaternion gyroAttitude = Input.gyro.attitude;
    Vector3 euler = gyroAttitude.eulerAngles;
    // 转换为[-180, 180]范围的Roll值
    float currentRoll = (euler.x > 180) ? euler.x - 360 : euler.x;
    float rollInput = currentRoll - initialRoll;
    
    // 仅用Roll输入控制物体绕Z轴旋转
    transform.Rotate(0, 0, rollInput * rotationSpeed * Time.deltaTime);
}

Android 原生实现

使用TYPE_ROTATION_VECTOR传感器获取融合姿态,提取Roll分量:

private SensorManager sensorManager;
private Sensor rotationVectorSensor;
private float initialRoll;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
    rotationVectorSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
}

@Override
protected void onResume() {
    super.onResume();
    sensorManager.registerListener(sensorListener, rotationVectorSensor, SensorManager.SENSOR_DELAY_GAME);
    // 可在用户点击校准按钮时执行初始Roll校准
    calibrateInitialRoll();
}

private void calibrateInitialRoll() {
    float[] rotationMatrix = new float[9];
    float[] orientation = new float[3];
    // 获取当前传感器事件作为初始校准值
    SensorEvent initialEvent = ...; 
    SensorManager.getRotationMatrixFromVector(rotationMatrix, initialEvent.values);
    SensorManager.getOrientation(rotationMatrix, orientation);
    initialRoll = orientation[2]; // Roll对应orientation数组第三个元素
}

private final SensorEventListener sensorListener = new SensorEventListener() {
    @Override
    public void onSensorChanged(SensorEvent event) {
        float[] rotationMatrix = new float[9];
        float[] orientation = new float[3];
        SensorManager.getRotationMatrixFromVector(rotationMatrix, event.values);
        SensorManager.getOrientation(rotationMatrix, orientation);
        
        float currentRoll = orientation[2];
        float rollInput = currentRoll - initialRoll;
        
        // 用rollInput控制物体绕Z轴旋转,忽略orientation[0](Yaw分量)
        updateObjectRotation(rollInput);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {}
};

private void updateObjectRotation(float rollInput) {
    // 实现物体绕Z轴旋转的逻辑
}

iOS 原生实现

使用CMDeviceMotion获取融合姿态,提取Roll值:

import CoreMotion

class GameViewController: UIViewController {
    let motionManager = CMMotionManager()
    var initialRoll: Double = 0
    let rotationSpeed: Double = 2.0

    override func viewDidLoad() {
        super.viewDidLoad()
        setupMotionManager()
    }

    private func setupMotionManager() {
        guard motionManager.isDeviceMotionAvailable else { return }
        motionManager.deviceMotionUpdateInterval = 1/60
        // 先校准初始Roll值
        motionManager.startDeviceMotionUpdates(to: .main) { [weak self] motion, error in
            guard let self = self, let motion = motion else { return }
            self.initialRoll = motion.attitude.roll
            self.motionManager.stopDeviceMotionUpdates()
            self.startReceivingMotionData()
        }
    }

    private func startReceivingMotionData() {
        motionManager.startDeviceMotionUpdates(to: .main) { [weak self] motion, error in
            guard let self = self, let motion = motion else { return }
            let currentRoll = motion.attitude.roll
            let rollInput = currentRoll - self.initialRoll
            
            // 仅用rollInput控制物体绕Z轴旋转
            self.updateObjectRotation(rollInput: rollInput)
        }
    }

    private func updateObjectRotation(rollInput: Double) {
        // 实现物体绕Z轴旋转的逻辑
    }
}

关键注意事项

  • 坐标系校准:不同平台的轴定义可能有差异,真机测试时需确认Roll分量是否对应你需要的倾斜动作,必要时调整轴映射。
  • 数据平滑:陀螺仪数据可能存在噪声,建议对Roll输入值做移动平均处理,让旋转动作更流畅。
  • 初始校准:添加校准逻辑,让用户可以在任意初始握持姿态下开始游戏,避免初始角度干扰控制。

内容的提问来源于stack exchange,提问作者Operator

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:53:15