Can someone show me an example of a script that rotates the camera in FPS view based off the rotation of a tablet or android device? Im at a lost on where to begin with this type of connection.
Here is a video on the basics of using the accelerometer:
http://unity3d.com/learn/tutorials/modules/beginner/platform-specific/accelerometer-input
And a post talking specifically about tilt:
But you will run into some bigger questions like āwhat is down?ā because players might play it different ways. Maybe you define it at start or maybe you allow player to recalibrate if they change positions. Ie sometimes I play games laying down with the device above me which would translate differently than if I was sitting up.
Thank you very much for the reply! I will look into these and see if it works!
Peter,
This is close to what Im looking for. But Iām looking for just the Camera to rotate without moving. the script for the example you provide does a good job of moving my camera on the X and Y directions when moving my phone, but the rotation is what Iām aiming for. I think something like this should do the trick, but itās not:
void Update ()
{
camera.transform.rotation = Input.gyro.attitude;
}
Any suggestion to get this to work. This didnāt move the camera at all when I rotated my phone.
Iāve confirmed it also doesnāt work on my device. Htc One Android 4.4.3 on unity 4.6.0f3. This post says to use Input.acceleration: Android Gyroscope not working ? - Questions & Answers - Unity Discussions
Were you able to get it to work from the link you just sent? I think Iām doing the conversion from JS wrong or something. But it sounds like they are on the right track to get it to work.
Sorry, I havenāt used UnityJs in forever. Here is some code I played with just now that should help put you in the right direction. Depending on your rotation axis and device orientation you will need to swap around x, y, and z. Youāll also probably want to figure out some smoothing. I like to have a proxy object for these things that lerps between the rotations multiplied by a set speed.
Input.acceleration seems like a bit of a misnomer. Maybe normalizedAngle or rotation or something would be more fitting.
Please bear with me on the quick code - Iām at work so trying to get it working on the down low ![]()
using UnityEngine;
using System.Collections;
public class gyro : MonoBehaviour {
Vector3 angle = Vector3.zero;
//TextMesh text; <-- I was using a text mesh to test displaying
void Start() {
//text = GetComponent<TextMesh>();
}
void Update() {
angle.x = Input.acceleration.x * 360;
transform.rotation = Quaternion.Euler(angle);
//text.text = Input.acceleration.x.ToString();
}
}
Thatās a start! itās definitely heading in the direction Iām looking for. But youāre right, I am getting some jittering and needing some smoothing. If you know a fix later Iād appreciate it!! Thanks for fixing the code!
Put a script similar to that on āproxyRotateObjectā
Then create a script on your object or camera to rotate and use something like this:
public GameObject rotateTarget; // Set this to be proxyRotateObject
public float matchSpeed = 1f; // The speed at which the camera will try to match the rotation of rotateTarget
void Update() {
transform.rotation = Quaternion.Lerp(transform.rotation, rotateTarget.transform.rotation, Time.deltaTime * matchSpeed);
}
This is how I do it, but not sure if thatās the most efficient way. In fact I recently read that getting the transform of a gameObject is the equivalent to GetComponent() so maybe instead of plugging in a GameObject in that first line do a Transform instead. But Iām not sure how to drag a Transform on. If that makes sense.
I wasnāt able to get your method to work. But this method was giving me some interesting results. It starts to work and has some smoothing, but still snaps into strange locations. Do you get the same results?
public float smooth = 2.0F;
public float tiltAngle = 10.0F;
void Update () {
float tiltAroundZ = Input.acceleration.x * tiltAngle;
float tiltAroundX = Input.acceleration.y * tiltAngle;
Quaternion target = Quaternion.Euler(tiltAroundX, 0, tiltAroundZ);
transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * smooth);
}
Peter,
This is actually working well for me now! My only issue is aiming the phone down is looking straight in the view. How do you suggest I fix this where holding the phone straight is also looking straight? Here is my code that his this working better:
//Gyro
public float smooth = 2.0F;
public float tiltAngle = 90.0F;
void Update ()
{
//Gyro
float tiltAroundZ = -Input.acceleration.x * tiltAngle * 50;
float tiltAroundX = Input.acceleration.y * tiltAngle * 50;
Quaternion target = Quaternion.Euler(tiltAroundX, tiltAroundZ, 0);
transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * smooth);
Iām glad that itās working, but Iām getting crazy results on my side with this code.
But if it is working for you, then you might be close. Not sure what axis is the one that would make yours point correctly. Find out which one, and try adding or subtracting 90 from that axis. This might take some guess and check, sorry Iām not able to properly replicate it.
After a little more testing, Iām also getting some crazy results. Oh well, back to the drawing boardā¦
When I get home from work Iāll see if I can put together a clean example.
Thanks Peter!
Peter,
Another round of testing. This actually works well for me again with this code. Only problem is trying to get it to start straight. Right now it starts with your phone faced straight down. Does this work for you?
[Range(0, 355)]
public float minAngle = 50f;
[Range(0, 355)]
public float maxAngle = 310f;
void Update ()
{
transform.Rotate(Vector3.right * Input.acceleration.y * 2.0f);
if (transform.eulerAngles.x >= minAngle && transform.eulerAngles.x <= (minAngle))
transform.eulerAngles = new Vector3(0f, 0f, minAngle);
if (transform.eulerAngles.x <= maxAngle && transform.eulerAngles.x >= (maxAngle))
transform.eulerAngles = new Vector3(0f, 0f, maxAngle);
transform.Rotate(Vector3.down * Input.acceleration.y * 2.0f);
if (transform.eulerAngles.z >= minAngle && transform.eulerAngles.z <= (minAngle))
transform.eulerAngles = new Vector3(0f, 0f, minAngle);
if (transform.eulerAngles.z <= maxAngle && transform.eulerAngles.z >= (maxAngle))
transform.eulerAngles = new Vector3(0f, 0f, maxAngle);
}
Yeah use z instead of x
Iāve put together a little script that should help. But Iāve realized something I never thought about before. This script gets the tilt of my device to move an axis on the camera like shaking my head yes. But I realize I have no idea how to get the axis equivalent to a no head shake with an accelerometer. I think that is how you want to use it right?
using UnityEngine;
using System.Collections;
public class rotate : MonoBehaviour {
float xRot, yRot, zRot;
public float rotSpeed = 20f;
void Update ()
{
// This tilts the axis of the camera like shaking a head yes
xRot = Input.acceleration.z * -180f;
// This tilts like a driving wheel to make it like shaking head no
yRot = Input.acceleration.x * -180f;
zRot = 0f;
transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.Euler(new Vector3(xRot, yRot, zRot)), Time.deltaTime * rotSpeed);
}
}
Both yes and no head motion, as we all being able to spin around 180 degrees behind in both directions (left and right). I feel like youāre on the right track but itās impossible for me to turn around. (Also getting a strange jittering, i tried adjusting ārotSpeedā but it still happens). Iāll keep playing with the code you sent to see if I can get some closer results.
Thanks a lot!
Unfortunately I havenāt had any luck. I also went back to the previous code I posted and took your advice on changing z instead of x, but still no luck. Were you able to get the code I last posted to work with a yes/no head shake motion in 180 degrees?
Hereās the code again Im referencing:
[Range(0, 355)]
public float minAngle = 50f;
[Range(0, 355)]
public float maxAngle = 310f;
void Update ()
{
transform.Rotate(Vector3.right * Input.acceleration.y * 2.0f);
if (transform.eulerAngles.x >= minAngle && transform.eulerAngles.x <= (minAngle))
transform.eulerAngles = new Vector3(0f, 0f, minAngle);
if (transform.eulerAngles.x <= maxAngle && transform.eulerAngles.x >= (maxAngle))
transform.eulerAngles = new Vector3(0f, 0f, maxAngle);
transform.Rotate(Vector3.down * Input.acceleration.x * 2.0f);
if (transform.eulerAngles.z >= minAngle && transform.eulerAngles.z <= (minAngle))
transform.eulerAngles = new Vector3(0f, 0f, minAngle);
if (transform.eulerAngles.z <= maxAngle && transform.eulerAngles.z >= (maxAngle))
transform.eulerAngles = new Vector3(0f, 0f, maxAngle);
}
I wasnāt able to. Your code was rotating at an angle on two axes based on the y value.
The code I posted has 20 as the speed which is way too fast and makes it choppy - my bad. I had turned that value down to 10 in unity. The reason that you are getting choppiness regardless of the value you put might be because you are changing the number in code but itās being overridden by the set value in the inspector panel in unity.
I should have been more clear about my thoughts on the no head shake angle. Iām not sure that itās possible. Iām not sure a deviceās accelerometer can detect rotation around an axis parallel to real world gravity. ![]()