简体   繁体   English

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

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

I would like to recreate one on one the rotation of the real life controller joystick (ie 360 controller) into a 3D joystick mesh (that resembles the 360 controller one).我想将现实生活中 controller 操纵杆(即 360 控制器)的旋转一对一地重新创建为 3D 操纵杆网格(类似于 360 Z594C103F2C6E04C0CAZAB059F031)。

I thought about doing it by rotating the joystick in the X axis according to the magnitude of the input (mapping it to a min and max rotation in the X axis).我考虑通过根据输入的大小在 X 轴上旋转操纵杆来做到这一点(将其映射到 X 轴上的最小和最大旋转)。 And then figure the angle of the input and apply it to the Y axis of the 3D joystick.然后计算输入的角度并将其应用于 3D 操纵杆的 Y 轴。

This is the code I have, the joystick tilts properly in the X axis but the rotation in the Y axis doesn't work:这是我的代码,操纵杆在 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);
}

I am not sure why is not working or even if I am doing it the right way (ie perhaps there is a more optimal way to achieve it).我不确定为什么不工作,或者即使我以正确的方式做(即也许有更优化的方法来实现它)。

Many thanks for your input.非常感谢您的意见。

I would recommend rotating it by an amount determined by the magnitude around a single axis determined by the direction.我建议将其旋转一定量,该量由围绕由方向确定的单个轴的大小确定。 This will avoid the joystick spinning around, which would be especially noticeable in cases of asymmetric joysticks such as pilots joysticks:这将避免操纵杆旋转,这在不对称操纵杆(例如飞行员操纵杆)的情况下尤其明显:

飞行员操纵杆示例

Explanation in comments:评论中的解释:

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);
}

This will work for joysticks where:这将适用于操纵杆,其中:

  1. the direction from its axle to its end is the local up direction,从它的轴到它的末端的方向是局部向上的方向,
  2. it should have zero (identity) rotation on neutral input, and它应该在中性输入上具有零(同一性)旋转,并且
  3. stickInput with y=0 should rotate the knob around the stick's forward/back axis, and stickInput with x=0 should rotate the knob around the stick's left/right axis. y=0 的stickInput应该围绕摇杆的前/后轴旋转旋钮,x=0 的stickInput应该围绕摇杆的左/右轴旋转旋钮。

操纵杆点在本地向上,操纵杆父级在操纵杆中立位置方向向上

Figure out the problem, atan2 returns the angle in radiants, however the code assumes it is euler degrees, as soon as I did the conversion it worked well.找出问题所在,atan2 返回以辐射为单位的角度,但是代码假定它是欧拉度,只要我进行了转换,它就运行良好。 I put the code here if anyone is interested (not the change in the atan2 function):如果有人感兴趣,我将代码放在这里(不是 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);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM