0
\$\begingroup\$

I am designing an endless runner style game like temple run. I need to move the player left and right based on the accelerometer input (tilting). The problem is that the accelerometer input is very sensitive. In other words the player is moving left even if the phone is held straight. I want to make the player to move smoothly like temple run game. (Player has a Rigidbody component attached to him.). Here is my initial code:

if (Input.acceleration.x < 0)
{
    this.transform.Translate(-0.3f, 0, 0);
}
else if (Input.acceleration.x > 0)
{
    this.transform.Translate(-0.3f, 0, 0);
}

Then I tried:

// Player is running in negative direction
// Input.acceleration > 0 moves the player right 
if (Input.acceleration.x < -0.2)
        {
            // this.transform.Translate(-0.3f, 0, 0);
            Vector3 dir = Vector3.zero;
            dir.x = Input.acceleration.x;
            if(dir.sqrMagnitude > 1)
            {
                dir.Normalize();
            }
            dir = dir * Time.deltaTime * horizontalMoveSpeed;
            transform.Translate(dir.x, 0 ,0 );
        }

        else if (Input.acceleration.x > 0.2)
        {
            // this.transform.Translate(0.3f, 0, 0);
            Vector3 dir = Vector3.zero;
            dir.x = Input.acceleration.x;
            if (dir.sqrMagnitude > 1)
            {
                dir.Normalize();
            }
            dir = dir * Time.deltaTime * horizontalMoveSpeed;
            transform.Translate(-dir.x, 0, 0);
        }

The problem in the edited new code is that the player moves only to the left even if the phone is tilted right. What is the mistake in my code?

I know that this question will get lots of down votes because this is a basic question. But unfortunately I am new to Unity and I cannot figure it out. What is the mistake?

\$\endgroup\$

2 Answers 2

0
\$\begingroup\$

Presumably you considered adding a window of tolerance into your check?

// Expose this in the Inspector so you can tune it to a value that feels good.
public float noTiltWindow = 0.2f;

// ... then later, in your movement function:

if (Input.acceleration.x < -noTiltWindow)
{
    transform.Translate(-0.3f, 0, 0);
}
else if (Input.acceleration.x > noTiltWindow)
{
    transform.Translate(+0.3f, 0, 0);
}

Or, equivalently:

if(Mathf.Abs(Input.acceleration.x) > noTiltWindow) {
    transform.Translate(Mathf.Sign(Input.acceleration.x) * 0.3f, 0f, 0f);
}

With this code, small jitter or bias in the accelerometer value won't be detected as leftward or rightward movement until you tilt your phone far enough to overcome the threshold.

Other ways you can improve this code:

  • Make the movement speed proportional to the amount of tilt, so the player gets a little warning when they're close to the threshold, before they start moving the wrong way at full speed.

  • Use Input.gyro.attitude or Input.gyro.gravity instead of Input.acceleration. This uses the phone's various sensors in tandem to compensate for errors or weaknesses in the accelerometer alone.

\$\endgroup\$
0
\$\begingroup\$

I used have used a Queue (or some other kind of circular array) to solve this problem before. You store a set number of “raw” previous values and average these values to come to the current value. Combined with the thresholds described in @DMGregory ‘s answer, this worked pretty well for me.

It takes a bit of trial and error to find the correct queue length.

The thresholds min and max movement get rid of a lot of the small jitters and instability. The averaged queue smooths the motion so you dont get big jumps.

Note that if the queue length is long, you’ll get what seems to be lag.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .