- Home /
Accelerometer calibration
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.
void Update () {
transform.Translate (Input.acceleration.x, 0, -Input.acceleration.z);
}
Answer by smallbit · Mar 21, 2015 at 07:16 AM
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();
}
//Edit i found the ORIGINAL POST
Been working through the above code but I can't seem to get any movement from my phone. Before I tried the above script I simply mapped Input.acceleration.x to a Vector2 which fed into my movement function which worked but I had to hold the phone at an awkward angle to get any motion in y. But now the player just stays in the spawn location and I'm not sure why (very new to scripting).Any help would be appreciated.
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Boundary
{
public float x$$anonymous$$in, x$$anonymous$$ax, y$$anonymous$$in, y$$anonymous$$ax;
};
public class PlayerController : $$anonymous$$onoBehaviour {
public Vector2 speed = new Vector2 (50, 50);
public Boundary boundary;
private Vector3 movement;
public GameObject shot;
public Transform shotSpawn;
public float fireRate;
private float nextFire;
$$anonymous$$atrix4x4 calibration$$anonymous$$atrix;
Vector3 wantedDeadzone = Vector3.zero;
void start()
{
calibrateAccelerometer ();
}
void calibrateAccelerometer()
{
wantedDeadzone = Input.acceleration;
Quaternion rotateQuaternion = Quaternion.FromToRotation (new Vector3 (0f, 0f, -1f), wantedDeadzone);
$$anonymous$$atrix4x4 matrix = $$anonymous$$atrix4x4.TRS (Vector3.zero, rotateQuaternion, new Vector3 (1f, 1f, 1f));
calibration$$anonymous$$atrix = matrix.inverse;
}
Vector3 getAccelerometer(Vector3 accelerator)
{
Vector3 accel = this.calibration$$anonymous$$atrix.$$anonymous$$ultiplyVector (accelerator);
return accel;
}
Vector3 _InputDir;
void Update()
{
//Retreive axis information
_InputDir = getAccelerometer (Input.acceleration);
//$$anonymous$$ovement depending on input
movement = new Vector3(_InputDir.x*speed.x, _InputDir.z*speed.y, 0);
if (Input.GetButton("Fire1") && Time.time > nextFire)
{
nextFire = Time.time + fireRate;
Instantiate(shot, shotSpawn.position, shotSpawn.rotation);
GetComponent<AudioSource>().Play ();
}
}
void FixedUpdate()
{
GetComponent<Rigidbody2D>().velocity = movement;
//$$anonymous$$eep player within screen boundary
transform.position = new Vector2
(
$$anonymous$$athf.Clamp(transform.position.x, boundary.x$$anonymous$$in, boundary.x$$anonymous$$ax),
$$anonymous$$athf.Clamp (transform.position.y, boundary.y$$anonymous$$in, boundary.y$$anonymous$$ax)
);
}
}
Thank you for this great solution, took 2 days to deeply understand the problem, and this solved everything like a charm.
Answer by stf940 · Feb 05, 2019 at 03:15 PM
i need same calibration. but i don t understand how to use this. can somebody help me?
Your answer
Follow this Question
Related Questions
Mobile tilting using Input.acceleration.z is not tilting properly on the right rotation 0 Answers
Why is gravity inside the Gyroscope class? 1 Answer
Match Object (Main Camera) To Gyroscope Rotation Rate 1 Answer
Using accelorometer with device parallel to table? 0 Answers
VR Camera using Input.acceleration 2 Answers