Search Unity

Thrustmaster Joystick Input

Discussion in 'Editor & General Support' started by Yo_Man, Jan 13, 2014.

  1. Yo_Man

    Yo_Man

    Joined:
    Nov 26, 2012
    Posts:
    1
    So I bought an old Thrustmaster USB Joystick to use on my next project.
    Basically I want to tear this joystick apart and mount the input axis to the handlebar of an ergometer. Thats why I dont want to spend extra money for a decent joystick.

    Testing the joystick in Unity, I encountered that all the axis are mapped wrong. The negative half is constantly 1, while the positive half goes from -1 to 1. Therefore only the bottom right quarter ist useable. It looks something like this:

    $thrustmaster.png

    In other games outside of Unity the Thrustmaster works just fine and my Xbox controller has no problems at all. Its just the Thrustmaster in Unity that is giving me a hard time.
    Is there a way to change the mapping or to bypass/replace the Input.GetAxis() function?

    Thanks in advance!
     
    juanitogan likes this.
  2. Douba

    Douba

    Joined:
    Oct 15, 2014
    Posts:
    2
    Thanks Yo_Man for this diagram - it had me thinking.
    I have had the same problem, but I finally figured it out. The thing is that Unity3D takes raw values from the gamepad driver and mangles them in a certain way.
    The short version: Decrease the sensitivity in the Input Manager to no more than 1/3 - 1/127 (roughly 0.3254). Then apply a complicated mapping that will give you appropriate values in [-1, 1].
    The long version: Unity3D seems to offset the driver's short int values by 64, then divide them by 64, then float-multiply them by the sensitivity as given in the Input Manager, and finally it clips them to [-1, 1]. Then there is the fact that there seem to be 258 joystick positions with three sign changes around zero. The data type seems to be 8 bits wide, so that 3 values must be repeated (these happen to be the ones around the center position).
    In the first figure, you can see why clipping leads to the behaviour you described.
    I have come up with a script to handle the mapping for the left stick. The right stick seems to work a little bit different, but I am sure that I will work it out soon.

    using UnityEngine;
    using System.Collections;
    /* Intended to unmangle Thrustmaster Dual Analog 3/4 joystick input in Unity3D
    * Currently works with the first set of axes (the left analog stick).
    * Comments welcome:
    Douba@Douba.de
    * Copyright 2014 by Ingo Schalk-Schupp
    * Free to use and modify, but mention my name.
    * */
    public class MapJoystick : MonoBehaviour {

    public string axisNameX = "", axisNameY = ""; // paste axes' Names from InputManager
    public float sensitivity = .1f; // paste value from InputManager. Must be lesser than or equal to .3254!
    public bool invertedX = false; // check if checked in the InputManager
    public bool invertedY = true; // ditto
    private float eps;
    private float scale;

    // Use this for initialization
    void Start () {
    scale = transform.parent.localScale.x * 5; // relates to the default 'plane' object
    eps = 2 * sensitivity / 127;
    }

    // Update is called once per frame
    void Update () {
    Vector3 pos = new Vector3(0f, 0f, 0f);
    if (axisNameX.Length > 0) {
    float inv = invertedX ? -1 : 1;
    float xMap = inv * ((((inv * Input.GetAxis(axisNameX) + 3f * sensitivity) / 2f) % (2f * sensitivity + eps / 2f)) / sensitivity - 1);
    pos += new Vector3(xMap * scale, 0f, 0f);
    }
    if (axisNameY.Length > 0) {
    float inv = invertedY ? -1 : 1;
    float yMap = inv * ((((inv * Input.GetAxis(axisNameY) + 3f * sensitivity) / 2f) % (2f * sensitivity + eps / 2f)) / sensitivity - 1);
    pos += new Vector3(0f, 0f, yMap * scale);
    }
    transform.localPosition = pos;
    }
    }
     

    Attached Files:

    Kjelle69 and juanitogan like this.
  3. Douba

    Douba

    Joined:
    Oct 15, 2014
    Posts:
    2
    I will post my current working code here, so it will not work out of the box. Sorry for that. STill hope it helps.
    --Douba

    using UnityEngine;
    using System.Collections;

    public class BallController2D : MonoBehaviour {
    public float maxForce = 1;

    public string axisNameX = "", axisNameY = ""; // paste axes' Names from InputManager
    public float sensitivity = .1f; // paste value from InputManager. Must be lesser than or equal to .3254!
    public bool invertedX = false; // check if checked in the InputManager
    public bool invertedY = true; // ditto
    public bool doubleY = false; // for right stick

    private float eps;
    private Transform eye;

    void Start () {
    eps = 2 * sensitivity / 127;
    eye = transform.FindChild("eye");
    }

    void FixedUpdate() {
    // get input force from stick
    Vector3 force = new Vector3(0f, 0f, 0f);
    if (axisNameX.Length > 0) {
    float inv = invertedX ? -1 : 1;
    float xMap = inv * ((((inv * Input.GetAxis(axisNameX) + 3f * sensitivity) / 2f) % (2f * sensitivity + eps / 3f)) / sensitivity - 1f);
    force += new Vector3(xMap * maxForce, 0f, 0f);
    }
    if (axisNameY.Length > 0) {
    float inv = invertedY ? -1 : 1;
    float yMap;
    if (doubleY)
    yMap = inv * ((((inv * Input.GetAxis(axisNameY) + 3f * sensitivity) / 2f) % (2f * sensitivity + eps / 3f)) / sensitivity - 1.5f) * 2;
    else
    yMap = inv * ((((inv * Input.GetAxis(axisNameY) + 3f * sensitivity) / 2f) % (2f * sensitivity + eps / 3f)) / sensitivity - 1f);
    force += new Vector3(0f, yMap * maxForce, 0f);
    }

    transform.rigidbody2D.AddForce(force);

    eye.localPosition = force * .1f / maxForce;
    }
    }
     
    Kjelle69 likes this.
  4. MarcoLuzuriaga

    MarcoLuzuriaga

    Joined:
    May 4, 2021
    Posts:
    1
    Wow, this is an old topic, but today I still have the same issue! I think I will try a slightly different approach.

    I opened up the Thrustmaster USB joystick and took apart the assembly for the potentiometer. I'm pretty confident I can 3D print a piece that will go in its place with a gear, then print a second gear with 1/2 the diameter of the first gear to mount on the pot. Then print a new mount for the potentiometer back to the joystick assembly. Then, turn the potentiometer to where it is at the 0 point such that moving the stick one way goes to +1 and the other way to -1. In theory, I will still have the full motion of the joystick but only using the range of the pot that is from -1 to 1. If I adjust the sensitivity slightly in Unity, I can make sure I don't hit the other inflection point.

    Tomorrow I will draft up my 3D model and start printing. Stay tuned! Of course, this is only for personal use, and any development based on this fix would not work for the general public... unless they buy my 3D printed joystick controller mod kits! Muah ha ha ha!