2
\$\begingroup\$

I have been trying to figure out how to implement controller input in my unity project. I figured out a lot of things except for how to take the 360 degree input of a thumbstick and apply that to a transform. I would like smooth movement in whatever degree the thumbstick is currently pushed towards instead of the 8 angle movement(I.E. up, down, left, right, down right, up right, down left, up left).

I have done a lot of research on this topic for a whole day now and have not come up with an answer that I could make sense of or implement correctly. I believe I need to use MathF.Atan2 but I am unsure how to incorporate it correctly.

I currently am in the process of figuring out how to do this and move a UI Image on the canvas to act as a virtual cursor for my controller support.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class JoystickCursor : MonoBehaviour {

public Image cursor;
RectTransform currentPosition;

// Use this for initialization
void Start ()
{

    currentPosition = GetComponent<RectTransform>();
}

// Update is called once per frame
void Update ()
{
    float x = Input.GetAxis("JoymouseX");
    float y = Input.GetAxis("JoymouseY");

    float angle = Mathf.Atan2(x, y);


    if (Input.GetAxis("JoymouseX") > 0)
    {
        currentPosition.localPosition += Vector3.right;
    }

    if (Input.GetAxis("JoymouseX") < 0)
    {
        currentPosition.localPosition += Vector3.left;
    }

    if (Input.GetAxis("JoymouseY") > 0)
    {
        currentPosition.localPosition += Vector3.down;
    }

    if (Input.GetAxis("JoymouseY") < 0)
    {
        currentPosition.localPosition += Vector3.up;
    }

    if (Input.GetAxis("JoymouseX") > 0 && Input.GetAxis("JoymouseY") > 0)
    {
        currentPosition.localPosition += Vector3.right;
        currentPosition.localPosition += Vector3.down;
    }
}
}

As you can see, my current script has not implemented the atan2 portion of it because anywhere I tried has failed to give the correct results. Can anyone help me figure out how to get smooth movement so the user can aim better with the cursor since it is going to act as a crosshair in the game? Any advice is appreciated! Thanks!

\$\endgroup\$
5
\$\begingroup\$

I'm going to let you in on a secret:

float x = Input.GetAxis("JoymouseX");
float y = Input.GetAxis("JoymouseY");

Here we have input with two components, an x and a y. That's a vector!

Vector2 input = new Vector2(
                      Input.GetAxis("JoymouseX"),
                     -Input.GetAxis("JoymouseY")  );

(Here I negated the y, since I noticed when y > 0 you want to move down. You can also do this by checking the "Invert" box when configuring the Y axis in the Input Manager)

Now you can just add this vector to your position:

currentPosition.localPosition += input;

(A Vector2 in Unity can implicitly convert to a Vector3 with z = 0)

You can verify that when x=1, this moves 1 unit to the right, same as your code above, and likewise for each other cardinal direction, so it matches at the extremes of each axis. And it also varies smoothly for all axis values in between. (That includes moving at reduced speed if the player doesn't push the joystick all the way, but we can discard this analog ramp-up if you prefer for your application)

This is a typical pattern in game calculations: if you have vector inputs and vector outputs, there's very often a way to get from one to the other without using angles in between. :)

We can extend this a bit further, to move at a defined speed independent of the current framerate:

currentPosition.localPosition += input * speed * Time.deltaTime

Out of the box, this will allow diagonal movement to go slightly faster than direct horizontal/vertical, since moving at a rate of 1.0 in two perpendicular directions at once means moving at a rate of 1.414 (sqrt(2)) combined. That's consistent with what you've written above, but if you want to keep a constant max speed you can clamp the input to a circle like so:

if(input.sqrMagnitude > 1.0f)
   input = input.normalized;
| improve this answer | |
\$\endgroup\$

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.