How to make gyroscope based controls useable

I am working on a ball rolling platformer game.

The game plays well (I think) with the WASD control scheme I have set up. I wish to make it a possibility to use the gyroscope on an android phone to play the game but I have a few issues.

  1. It seems almost unresponsive, but at the same time, it seems almost to sensitive.
  2. It’s near impossible to play - maybe it’s a lack of practice, but it’s absurdly difficult.

Things I’ve tried: making the slowing down of the ball use a higher modifier for the force applied then the speeding up of the ball, adjusting the the value I’m multiplying by using in relation to gyroscope.attitude at the beginning (using as a home base - if I relaunch the scene it doesn’t seem to accelerate at all after using this method) .

The apk asks for internet access because it phones home for hiscore management, aside from that it uses only the gyroscope and only unity functions.
A link to download the apk

My code:

if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow) || Input.gyro.attitude.y > (defaultValue.y + reqOffset))
            {
#if  UNITY_ANDROID
                float mobileMod = 1;
                if (rigidbody.velocity.z > 0)
                {
                    mobileMod = 0.7f * Mathf.Abs(Input.gyro.attitude.z);
                }
                else if (rigidbody.velocity.z < 0)
                {
                    mobileMod = 1.0f * Mathf.Abs(Input.gyro.attitude.z);
                }
#else
                float mobileMod = 1f;
#endif
                //Forward
                rigidbody.AddForce(Forward * MoveModifier * mobileMod);
            }
            if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow) || Input.gyro.attitude.x > (defaultValue.x + reqOffset))
            {
#if  UNITY_ANDROID
                float mobileMod = 1;
                if (rigidbody.velocity.x < 0)
                {
                    mobileMod = 0.7f * Mathf.Abs(Input.gyro.attitude.x);
                }
                else if (rigidbody.velocity.x > 0)
                {
                    mobileMod = 1.0f * Mathf.Abs(Input.gyro.attitude.x);
                }
#else
                float mobileMod = 1f;
#endif
                //Right
                rigidbody.AddForce(Right * MoveModifier * mobileMod);
            }
            if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow) || Input.gyro.attitude.y < (defaultValue.y - reqOffset))
            {
#if  UNITY_ANDROID
                float mobileMod = 1;
                if (rigidbody.velocity.z < 0)
                {
                    mobileMod = 0.7f * Mathf.Abs(Input.gyro.attitude.z);
                }
                else if (rigidbody.velocity.z > 0)
                {
                    mobileMod = 1.0f * Mathf.Abs(Input.gyro.attitude.z);
                }
#else
                float mobileMod = 1f;
#endif
                //Backwards
                rigidbody.AddForce(Backwards * MoveModifier * mobileMod);
            }
            if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow) || Input.gyro.attitude.x < (defaultValue.x - reqOffset))
            {
#if  UNITY_ANDROID
                float mobileMod = 1;
                if (rigidbody.velocity.x > 0)
                {
                    mobileMod = 0.7f * Mathf.Abs(Input.gyro.attitude.x);
                }
                else if (rigidbody.velocity.x < 0)
                {
                    mobileMod = 1.0f * Mathf.Abs(Input.gyro.attitude.x);
                }
#else
                float mobileMod = 1f;
#endif
                //Left
                rigidbody.AddForce(Left * MoveModifier * mobileMod);
            }

I once did the game like this, also had similar problems, what worked for me was to get only half of the input from gyro into consideration (from 0-0.5, treat 0.5 as maximum) and project it to the board rotation. Than instead of multiplying it by constant, I set a curvefield (evaluated in function of gyro) variable with straight line going from high value to low. So when my gyro move is tiny it will be multiplied by higher value i.e 2 (don’t remember exact value), but than if the gyro is close to 0.5 the value from curve is for instance 0.8. That provides good responsiveness with tiny moves and keep extreme moves under control. You can probably test it using unity remote :slight_smile:

Hope it helps

Edit// setting up ball physic and physical materials for each collision was also an important step.