So I am making a 3d game on android and am using the accelerometer to move. When I play the game on Unity Remote, it is very hard to control my character because I have to hold my android at a weird angle. I have been trying for hours to figure this out and have had no luck. Is it possible to make it so that I can either zero out or calibrate the accerlerometer when I start the game? Thanks.
There is two general solutions on forums if you google for them, one is to store and angle between input 0,0,0, and current input, save is as initial rotation and than add it to the Input acceleration upon game starts (or hit button) other is using a Matrix4x4. The first one did not work for me in situation when I put device flat on the table, than rotation along z axis gives the same value regardless of the direction. So I use another solution copied from a post on forums (I cannot find it now…) So what it does Is on calling calibration method, you store a initial rotation between device rotation and vector down, than you store it in 4X4 Matrix created using TRS method (Transform Rotation Scale). Than whenever you call for the input (getAccelerometer method) you multiply current input by the matrix, so it works as described above giving you input as if your initial position was equivalent to device with input = Vector3.zero;
//declare matrix and calibration vector
Matrix4x4 calibrationMatrix;
Vector3 wantedDeadZone = Vector3.zero;
...
//Method for calibration
void calibrateAccelerometer()
{
wantedDeadZone = Input.acceleration;
Quaternion rotateQuaternion = Quaternion.FromToRotation(new Vector3(0f, 0f, -1f), wantedDeadZone);
//create identity matrix ... rotate our matrix to match up with down vec
Matrix4x4 matrix = Matrix4x4.TRS(Vector3.zero, rotateQuaternion, new Vector3(1f, 1f, 1f));
//get the inverse of the matrix
calibrationMatrix = matrix.inverse;
}
//Method to get the calibrated input
Vector3 getAccelerometer(Vector3 accelerator){
Vector3 accel = this.calibrationMatrix.MultiplyVector(accelerator);
return accel;
}
//Finally how you get the accelerometer input
Vector3 _InputDir;
void Update()
{
_InputDir = getAccelerometer(Input.acceleration);
//then in your code you use _InputDir instead of Input.acceleration for example
transform.Translate (_InputDir.x, 0, -_InputDir.z);
}
//you also want to calibrate the device on start so regardless of how user is holding it the initial position will be treated as 0 Input.
void Start()
{
calibrateAccelerometer();
}