# Calculate the displacement of device in unity

I'm making a 3D game in unity where the object should move forward and backward as the android device moves/accelerates in the Z axes. ie. When the player moves the devise in the direction of the +ve Z axis, the object should move forward, and when the player moves the devise in the direction of the -ve Z axis, the object should move backward.

This game is a multiplayer game, and the players will move in a large football field.

My idea to do this is using the accelerometer to calculate the acceleration of the device, then integrate the data of acceleration to get the device speed in the Z axis. and use the speed to move the device.

Using this equation

V2=V1 + ΔA . ΔT
Where
V2 : final velocity.
V1 : initial velocity.
ΔA : difference between the initial and final acceleration.
ΔT : difference between the initial and final time.

At first I tried to use kinematic equations to calculate the final speed, but I realized then that it can be only used when acceleration is constant. So a friend of me who studies physics differentiated this equation for me to use it when acceleration is variable.

I know that there will be some error in calculating the accurate displacement, and that the error will increase after the integration of acceleration, but this small percentage of error is okay for my application; I thought at first in using GPS instead of accelerometer but I found that GPS accuracy will be less than the sensors.

I know also that the error will be incredibly high after some time, so I reset the values of acceleration and velocity every 10 seconds. I'm also using a low-pass filter to reduce the noise of the sensor.

public class scriptMove : MonoBehaviour
{
const float kFilteringFactor = 0.1f;

public Vector3 A1;
public Vector3 A2;
public Vector3 A2ramping; // for the low-pass filter
public Vector3 V1;
public Vector3 V2;

public int SpeedFactor=1000; //this factor is for increasing acceleration to move in unity world

void resetAll()
{
Input.gyro.enabled = true;
A2 = Vector3.zero;
V1 = Vector3.zero;
V2 = Vector3.zero;
A2ramping = Vector3.zero;
}
// Use this for initialization
void Start()
{
InvokeRepeating("resetAll", 0, 10);
}

//http://stackoverflow.com/a/1736623
Vector3 ramping(Vector3 A)
{
A2ramping = A * kFilteringFactor + A2ramping * (1.0f - kFilteringFactor);
return A - A2ramping;
}

void getAcceleration(float deltaTime)
{
Input.gyro.enabled = true;

A1 = A2;
A2 = ramping(Input.gyro.userAcceleration) * SpeedFactor;

V2 = V1 + (A2 - A1) * deltaTime;

V1 = V2;
}

//Update is called once per frame
void Update()
{

getAcceleration(Time.deltaTime);

float distance = -1f;
Vector3 newPos = transform.position;

transform.Translate(Vector3.forward * Time.deltaTime * V2.z * distance);
}
}


## The problem:

My code doesn't work always as expected when I move with the device;

• Sometimes when I move forward (in the +ve Z axis of the device) the object moves forward also, but sometimes it doesn't move at all.
• Sometimes when I'm still in my position the object moves alone by itself.
• Sometimes when I move forward and suddenly stop, the object does not stop.

# My questions:

• Are those strange behaviors because of the accuracy of the device, or is there something I'm missing in my code.
• If I'm missing something in my code, What is it?
• I searched a lot about methods to get the most accurate position of the device, and I found that I can integrate GPS with accelerometer, how can I do this with my code in unity?
• Sorry to burst your bubble, but using the accelerometer with the GPS would actually make the GPS error a bit smaller, but since the accelerometer might be required to estimate displacements in the order of centimeters and the GPS, at best, does +/- 3 meters, one can only understand what to expect. Jul 1, 2016 at 11:52
• Your problem is quite tough and dare I say open. I've seen quite some implementations on it, most of which were tightly coupled with a certain sensor technology and were not portable to other devices. Your problem is the dreaded dead reckoning problem. E.g. researchgate.net/publication/… Jul 1, 2016 at 11:53

Well your code is very smart but Unity has already done those calculations for you and you can just use

void Update ()
{
transform.Translate(0, 0, -Input.acceleration.z);
}


as it will take the device rotation in the world and translate it into Unity same way it behaves with WASD movement.

EDIT:

a simple example code,

public class DeviceMovement : MonoBehaviour {

public float speed = 10f;

void start() {

}

void Update () {

transform.Translate(0, 0,

(-1 * Input.acceleration.z *speed * Time.deltaTime)); // adds movement on the Z axis alone.

}

}

• I tried to use Input.acceleration before. It doesn't give me the acceleration of the device, it just gives me the device's rotation. Jun 24, 2016 at 9:44
• which is what you want to base your acceleration on, if you take the current position and add Input.acceleration to it and divide it by desired speed you will get the desired acceleration. Jun 24, 2016 at 10:04
• It still doesn't work with me :( When I add this line in the update method transform.Translate(0, 0, -Input.acceleration.z/30);, the object moves forward and backward only when I rotate the device. And it doesn't move when I move forward or backward at all! I also tried the unity example about it but the example didn't work also :( Jun 24, 2016 at 10:35
• look at that example it normalize the position according to the other axises, you should just rotate sideways and accelerate forward according to your Z axis, ill find some time and ill write down the entire script, but I dont have a device I can actually check it with. Jun 24, 2016 at 18:33
• I'll appreciate that very much. thanks in advance for your help :) Jun 24, 2016 at 19:39