Excuse me for a vague title, I don’t really know how else to explain it.
So, I’m developing my graduation project, which is a VR game with a home-made VR controller. the controller is a gun which contains a gyroscope to measure the angle of the gun. Through a bluetooth connection I push the 3 axis to unity.
Now, in unity, I have a google cardboard setup, with my FPS gun prefab attached underneath it as a child:

The gameobject with name VR setup rotates with the direction of the player his or her head. The Gun holder object has a FPS model with a gun pointing straight forward at a local rotation of 0, 0, 0.
Now, when I start the game with my gun straight forward, everything works fine. I am able to rotate my head around, and the gun is alligned with the controller I am holding. Now, because the gun-controller can, for example, lay on my desk when launching the game, and pick it up and hold it straight forward, it’ll be in a different angle, and I actually have to point the gun to the left, right, up, or whatever direction to get it in front of my in-game.
To catch this, I added a button to my gun controller. The idea behind this is that the user can hold the gun straight forward, and when the button is pressed, it’ll sync the in-game gun straight forward too.
Solid plan? yes, if it would work.
I’ll explain what I tried here:
public void GetRotation() {
newRot = Quaternion.Euler(z, x, -y);
if (isSync) {
isSync = false;
syncRot = objectVisual.transform.rotation;
}
newRot *= Quaternion.Inverse(syncRot);// * Quaternion.Euler(0, -30, 0) ;
//newRot = Quaternion.Euler(newRot.eulerAngles.x - syncRot.eulerAngles.x, newRot.eulerAngles.y - syncRot.eulerAngles.y, newRot.eulerAngles.z - syncRot.eulerAngles.z);
}
The function GetRotation gets called every frame, right after I received and decoded my bluetooth data into the global variables x, y and z. Because the gyroscope is not alligned in my gun to it’s own axis, I had to switch some of these values to create the Quaternion called newRot.
EDIT: objectVisual is the gameObject called gun holder in the hierarchy picture! The newRot is also applied to the objectVisual, or gun holder gameobject. Because it is a child of the head rotating transform, substracting the localrotation from itself should put it to 0, right?
When the button was pressed on my gun controller, it’ll set the isSync boolean to true so I know I want to update my syncRotation the next time I calculate my rotation.
Now, when I want to sync, I grab the current rotation on the gun and subtract is from the new rotation I decoded from my bluetooth device.
I made a nice drawing to explain it some more:

So, if I was to press the synchronize button on my gun, this should happen:
The received rotation from my bluetooth device is (0, 45, 0), my in-game rotation is (0, 0, 0). The sync rotation should be (0, 45, 0), because every frame, we’re gonna subtract the sync rotation from the received rotation, to get it synchronized straight forward => newRot = newRot - syncRot => newRot = (0, 45, 0) - (0, 45, 0) = (0, 0, 0), right??
The result however, is that it only snaps to (0, 0, 0) when it’s a little bit away from (0, 0, 0). When I point my arm completely to the right, it synchronized to something like (0, 20, 0). Actually it’s always different with a different angle ![]()
Is there something wrong with my code? I have tried many different ways, such a substracting euler values, or raw x, y, z, w values, but nothing seems to work.
Thanks guys, and sorry for this big ass long post.