Unity - 对对象应用两个局部旋转(尝试将控制器操纵杆的旋转重新创建为 3D 网格操纵杆)

Unity - Apply two local rotations to object (trying to recreate the rotation of a controller joystick into a 3D mesh joystick)

我想将真实控制器操纵杆(即 360 控制器)的旋转一对一地重新创建为 3D 操纵杆网格(类似于 360 控制器)。

我考虑过根据输入的大小在 X 轴上旋转操纵杆(将其映射到 X 轴上的最小和最大旋转)。然后计算输入的角度并将其应用于3D摇杆的Y轴。

这是我的代码,操纵杆在X轴上正确倾斜但在Y轴上旋转不起作用:

    public void SetStickRotation(Vector2 stickInput)
{
    float magnitude = stickInput.magnitude;

    // This function converts the magnitude to a range between the min and max rotation I want to apply to the 3D stick in the X axis
    float rotationX = Utils.ConvertRange(0.0f, 1.0f, m_StickRotationMinX, m_StickRotationMaxX, magnitude);
    
    float angle = Mathf.Atan2(stickInput.x, stickInput.y);
    
    // I try to apply both rotations to the 3D model
    m_Stick.localEulerAngles = new Vector3(rotationX, angle, 0.0f);
}

我不确定为什么不起作用,或者即使我以正确的方式进行操作(即也许有更优化的方法来实现它)。

非常感谢您的意见。

我建议将它旋转一定量,该量由围绕由方向确定的单个轴的幅度确定。这将避免操纵杆旋转,这在非对称操纵杆(例如飞行员操纵杆)的情况下尤其明显:

评论中的解释:

public void SetStickRotation(Vector2 stickInput)
{
    /////////////////////////////////////////
    // CONSTANTS (consider making a field) //
    /////////////////////////////////////////

    float maxRotation = 35f; // can rotate 35 degrees from neutral position (up)

    ///////////
    // LOGIC //
    ///////////

    // Convert input to x/z plane
    Vector3 stickInput3 = new Vector3(stickInput.x, 0f, stickInput.y);

    // determine axis of rotation to produce that direction
    Vector3 axisOfRotation = Vector3.Cross(Vector3.up, stickInput3);

    // determine angle of rotation
    float angleOfRotation = maxRotation * Mathf.Min(1f, stickInput.magnitude);

    // apply that rotation to the joystick as a local rotation
    transform.localRotation = Quaternion.AngleAxis(angleOfRotation, axisOfRotation);
}

这适用于操纵杆,其中:

  1. 从它的轴到它的末端的方向就是局部向上的方向,
  2. 它应该在中性输入上有零(身份)旋转,并且
  3. y=0 的
  4. stickInput 应该围绕摇杆的 forward/back 轴旋转旋钮,而 x=0 的 stickInput 应该围绕摇杆的 left/right 旋转旋钮轴.

找出问题所在,atan2 returns 以辐射点为单位的角度,但是代码假设它是欧拉度,一旦我进行了转换,它就运行良好。 如果有人感兴趣,我把代码放在这里(不是 atan2 函数中的更改):

public void SetStickRotation(Vector2 stickInput)
{
    float magnitude = stickInput.magnitude;

    // This function converts the magnitude to a range between the min and max rotation I want to apply to the 3D stick in the X axis
    float rotationX = Utils.ConvertRange(0.0f, 1.0f, m_StickRotationMinX, m_StickRotationMaxX, magnitude);
    
    float angle = Mathf.Atan2(direction.x, direction.y) * Mathf.Rad2Deg;
    
    // Apply both rotations to the 3D model
    m_Stick.localEulerAngles = new Vector3(rotationX, angle, 0.0f);
}