0
\$\begingroup\$

I am implementing a weapon wheel in Unity and I have most of it all worked out, but am struggling with one issue:

My weapon wheel looks a bit like this one (example only):

enter image description here

And mine is for something else, not weapons.. but that doesn't matter.

There is no mouse involved.. the idea is to spin the wheel left and right until you've selected the item you want.. the selected one would be the one in the top most position (the example above is the bottom most position, it seems).. Anyway, I have it moving left and right just fine.. the problem now is trying to figure out which button (yes, they are implemented as UI buttons) is currently in the selected position.

My initial thoughts are

  1. To calculate the center X, Y pair of the "selected" location and store those..

  2. When user hits action button to select, then iterate through the 8 buttons I have in that weapon wheel and..

  3. Calculate the current X and Y of each button in the loop

  4. If the button overlaps the "selected" location, then invoke that button's click()

This is proving to be a real pain in the neck though.. for example, I have found that the button transform's positon is always 0,0 until you show the UI at least once.. so I have to use Update() instead of Start().. In addition, trying to calculate the overlap means needing to add width of button to current X and height to current Y and getting pixel width does not seem to be an easy task.

Is there some simpler way to do this? How can I have a "selected" button on my weapon wheel without too much fuss like this? And if this really is the only way, then please let me know how I can get the pixel width and height of buttons.

\$\endgroup\$
  • 1
    \$\begingroup\$ If your buttons are equally spaced like this, then worrying about pixel positions and widths and heights seems like overkill. Just track the rotation angle of the wheel as a whole, and wrap/round it into one of 8 equally-spaced buckets. That rounded value is now the selected index in your array of buttons. \$\endgroup\$ – DMGregory Jul 16 '20 at 11:06
  • 1
    \$\begingroup\$ Either the above - or why not map your input directly to a normalised float value for percentage. That way you have the percentage round the wheel, which can be used to drive the rotation of the UMG element and the selection \$\endgroup\$ – Natalo77 Jul 16 '20 at 12:17
  • \$\begingroup\$ Bloody fantastic.. @DMGregory I went with yours. Will post the solution below. I would say you should post the answer and I mark it as the solution, but I remember you're the same guy who helped me before and said you didn't want that. Assuming the same here? \$\endgroup\$ – Matt Jul 16 '20 at 12:32
1
\$\begingroup\$

Okay, I went with @DMGregory's answer (see his comment above).

So I was already tracking the rotation angle of the wheel anyway.. then all I needed to do was normalize the degrees between 0 and 360 and then figure out which button is at which degree... like so:

An extension method for the normalizing of degrees first:

public static int NormalizeCircleDegrees(this int orientation)
{
    orientation %= 360;

    if (orientation < 0)
    {
        orientation += 360;
    }

    return orientation;
}

And then this method:

private Button GetSelectedButton()
{
    int normalizedDegrees = currentRotation.NormalizeCircleDegrees();

    switch (normalizedDegrees)
    {
        case 0: return Buttons[0];
        case 45: return Buttons[1];
        case 90: return Buttons[2];
        case 135: return Buttons[3];
        case 180: return Buttons[4];
        case 225: return Buttons[5];
        case 270: return Buttons[6];
        case 315: return Buttons[7];
        default: return Buttons[0];
    }
}

Just make sure the buttons are in the right order and voila! Much simpler...

\$\endgroup\$
  • \$\begingroup\$ Nice solution! I presume you increment your rotation in discrete 45 degree clicks, so it can never be a little off, like at 91 degrees instead of 90? \$\endgroup\$ – DMGregory Jul 16 '20 at 12:43
  • \$\begingroup\$ That's right.. always +/- 45 degrees. It seems to be working very well. Thanks for the help \$\endgroup\$ – Matt Jul 16 '20 at 12:46
  • 1
    \$\begingroup\$ You can use division to get the index directly, without your switch statement: int index = (orientation/45) & 7; return Buttons[index]; \$\endgroup\$ – DMGregory Jul 16 '20 at 12:49
  • \$\begingroup\$ Ah, that you are right. Thank you yet again. \$\endgroup\$ – Matt Jul 16 '20 at 12:55
  • 1
    \$\begingroup\$ I'm staring the potential for a beautiful data driven radial menu tool in the face but I just know it's so overkill for what you need. \$\endgroup\$ – Natalo77 Jul 16 '20 at 13:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.