I'm using the latest googleVr SDK(1.10) but I tested some example scenes from unity like castle defence and I notice the view began to drift when I put the phone on the table. is there a way to prevent this drift programatically?
I saw some videos to correct the gyroscope on samsung but I want some code to prevent this
It's still a non solved issue, as explained in this post:
GvrViewerMain rotates the camera yourself. Unity3D + Google VR
But according to your needs, you may find usefull the following workaround.
The idea is to find the delta rotation and ignore it if too small.
using UnityEngine;
public class GyroCorrector {
public enum Correction
{
NONE,
BEST
}
private Correction m_correction;
public GyroCorrector(Correction a_correction)
{
m_correction = a_correction;
}
private void CorrectValueByThreshold(ref Vector3 a_vDeltaRotation, float a_fXThreshold = 1e-1f, float a_fYThreshold = 1e-2f, float a_fZThreshold = 0.0f)
{
// Debug.Log(a_quatDelta.x + " " + a_quatDelta.y + " " + a_quatDelta.z );
a_vDeltaRotation.x = Mathf.Abs(a_vDeltaRotation.x) < a_fXThreshold ? 0.0f : a_vDeltaRotation.x + a_fXThreshold;
a_vDeltaRotation.y = Mathf.Abs(a_vDeltaRotation.y) < a_fYThreshold ? 0.0f : a_vDeltaRotation.y + a_fYThreshold;
a_vDeltaRotation.z = Mathf.Abs(a_vDeltaRotation.z) < a_fZThreshold ? 0.0f : 0.0f;//We just ignore the z rotation
}
public Vector3 Reset()
{
return m_v3Init;
}
public Vector3 Get(Vector3 a_v3Init)
{
if (!m_bInit)
{
m_bInit = true;
m_v3Init = a_v3Init;
}
Vector3 v = Input.gyro.rotationRateUnbiased;
if (m_correction == Correction.NONE)
return a_v3Init + v;
CorrectValueByThreshold(ref v);
return a_v3Init - v;
}
}
... And then use something like this in the "UpdateHead" method from "GvrHead":
GvrViewer.Instance.UpdateState();
if (trackRotation)
{
var rot = Input.gyro.attitude;//GvrViewer.Instance.HeadPose.Orientation;
if(Input.GetMouseButtonDown(0))
{
transform.eulerAngles = m_gyroCorrector.Reset();
}
else
{
transform.eulerAngles = m_gyroCorrector.Get(transform.eulerAngles);//where m_gyroCorrector is an instance of the previous class
}
}
You may find some problems. Mainly but not exclusive:
There will be a latence problem when moving the head as there is an offset to detect the movement
You are dealing with relative positions that come with imprecisions. So you are not 100% sure to find the same position
when doing the opposite movement.
You are using euler representation instead of quaternion, and it seems to be less accurate.
You may also be interested in these links speaking about the field:
http://scholarworks.uvm.edu/cgi/viewcontent.cgi?article=1449&context=graddis
Gyroscope drift on mobile phones
and this piece of code :
https://github.com/asus4/UnityIMU
Hope it can help,
Related
I'm newbie in Unity3D scripting and trying to learn how it works internally for my simple projects, what are the best practices. Here I have a simple scene with a cube in it and trying to animate it, going left to certain point in time, then reversing back to negative value and then back in loop (on x axis). Direction is set in class public boolean property. By default it is negative value (which means it should go in positive direction, sorry for confusion). If it is positive it should go negative. However I have noticed that when I change this boolean value in Update method of script, it reverses back to original value? (when set to true, default is false). Then my object gets stack between going true and false and not moving in any direction. However if I set this property as static property in class, it does not resets and works just as intended (loops fine). I do not know why is it resets and here I'm completely confused.
public class CubeAnim : MonoBehaviour
{
public bool directionnegative;
// Update is called once per frame
void Update()
{
float nv = 25.0f * Time.deltaTime;
float posx = transform.position.x;
if (posx > 20.0f)
{
if (!directionnegative)
{
directionnegative = true;
}
}
else if (posx < -20.0f)
{
if (directionnegative)
{
directionnegative = false;
}
}
if(directionnegative)
{
nv = -(nv);
}
transform.Translate(nv, 0, 0);
deltaTime += (Time.deltaTime - deltaTime) * 0.1f;
float fps = 1.0f / deltaTime;
string log = "posx: " + transform.position.x + "\ndir: " + directionnegative + " transx: " + nv + "\nfps: " + Mathf.Ceil(fps).ToString();
Debug.Log(log);
}
}
And if I declare directionnegative as static bool script works fine and cube animation is properly going in one direction, then in another direction, then reverses:
public static bool directionnegative;
I'm trying to come up with a calculated way to compare current speed vs distance to the next waypoint, with the end goal that the computer car makes a decision to "coast," brake, or keep the throttle on in the best way while turning the best way possible so that it doesn't OVERSHOOT the waypoint (like the Standard Unity assets car currently does when using the waypoint AI). I feel like there's a few things I'm failing to grasp, however. I've had to set up a TON of barriers and something I call "PowerZones" (zones that control the amount of brake and engine torque on the car in terms of percentages). Here's my current course below, which is of course incomplete in waypoints, but the point is to note how many of these zones and obstacles there is. I really don't feel there should HAVE to be this many!
However, the reason that I have SO many is because it's been kinda difficult for me to come up with an ideal function to optimize these kinds of driving and steering decisions as the opponent. Here's the Drive and Steer functions for the vehicle (some of which are based on an existing Eyemaginary tutorial):
private void Drive()
{
float currDistFromWP = Vector3.Distance(transform.position, nodes[currentNode].position);
float speed = rb.velocity.magnitude;
float timeFloatLeft = currDistFromWP / speed;
Vector3 relativeVector = transform.InverseTransformPoint(nodes[currentNode].position);
float newSteer = (relativeVector.x / relativeVector.magnitude);
Debug.Log("Steer to set: " + newSteer);
Debug.Log("Current distance: " + currDistFromWP);
if ((timeFloatLeft < 1f || Mathf.Abs(newSteer) > .5f) && speed > 5)
{
Debug.Log("Coasting...");
im.throttle = 0;
}
else
{
im.throttle = 1;
}
}
private void ApplySteer()
{
if (avoiding)
return;
Vector3 relativeVector = transform.InverseTransformPoint(nodes[currentNode].position);
float newSteer = (relativeVector.x / relativeVector.magnitude);
im.steer = newSteer;
}
Here is my waypoint updating function:
private void CheckWaypointDistance()
{
float currDistFromWP = Vector3.Distance(transform.position, nodes[currentNode].position);
//Debug.Log("Current distance from waypoint: " + currDistFromWP);
if (currDistFromWP < 1.1f)
{
im.brake = false;
if(currentNode == nodes.Count - 1)
{
currentNode = 0;
}
else
{
currentNode++;
}
}
else if (currDistFromWP < 10f)
{
im.brake = true;
}
}
I feel like I could be making this harder than I need to somehow. Or maybe I'm just needing to consider more variables. Does anyone have any tips to make this a little more tight in terms of AI logic? I'm happy to show more code if needed, but the idea is to have a Car Controller class that's used by BOTH the player and AI to DRIVE the car, and then the AI making the best decisions in a way the player would need to drive it in a separate class. The code from above is the separate AI decision making component.
I'm currently learning Unity. I have learnt and did many projects and started making a new one about cars. My goal is NOT to achieve realistic physics. I'm trying to have a 0 slip.
I have done all the steps about the wheelcolliders, velocity, rotation, and overall movement. Currently I'm struggling to disable the car slip.
I don't want the car to slip at all. I tried using transform and change the position, but that isn't the method that I want to use.
Using the following method, I'm doing the acceleration:
private void doAccelerate() {
currentSpeed = (int) (rb.velocity.magnitude * 3.6f);
if (!hasBraked) {
if (hasReachedMax) {
rb.velocity = new Vector3(rb.velocity.x, rb.velocity.y, maxVelocity);
} else {
if (currentSpeed < maxSpeed) {
rearDriverW.motorTorque = m_verticalInput * motorForce * motorAccelerate;
rearPassengerW.motorTorque = m_verticalInput * motorForce * motorAccelerate;
} else if (currentSpeed > maxSpeed) {
hasReachedMax = true;
}
}
}
}
The following two pics provide the UI units for the Rigidbody and WheelColliders.
This pic, and this one.
I would some suggestions to apply 0 slip. I have tried playing with the value, yet I didn't reach the perfect values. Nevertheless, I didn't understand it correctly. That's why I didn't know.
In a Unity VR app I'm building, I'm trying to rotate an object that is currently 'being held'. The technique I'm using is to find the desired rotation and feed it into the target objects Rigidbody via Rigidbody.MoveRotation. This works well when I use a test quaternion exposed in the inspector, but my quaternion math is completely failing me when it comes to finding the target rotation I want. I've got the position tracking working perfectly, it's just the rotation thats killing me!
The desired outcome is that the target object in question keeps its current rotation (from the moment its picked up) and simply applies the frame-by-frame difference of the VR controller. I thought this would be pretty straight forward, but I'm getting strange results. This is what I have so far:
public Rigidbody targetRigidbody;
public Quaternion controllerRotationSnapshot;
public Quaternion targetRotationSnapshot;
public float grabRadius = 0.25f;
public Collider[] grabResults;
Quaternion deltaRotation;
void Awake() {
grabResults = new Collider[5];
}
// This is triggered externally
public void Pickup() {
Physics.OverlapSphereNonAlloc(transform.position, grabRadius, grabResults);
for (int i = 0; i < grabResults.Length; i++) {
if (grabResults[i] != null) {
if (grabResults[i].CompareTag("Grabbable")) {
targetRigidbody = grabResults[0].GetComponent<Rigidbody>();
targetRotationSnapshot = targetRigidbody.transform.rotation;
i = grabResults.Length;
}
}
}
controllerRotationSnapshot = transform.rotation;
}
public void LetGo() {
if (!targetRigidbody) {
return;
}
targetRigidbody = null;
grabResults = new Collider[5];
}
void FixedUpdate() {
if (!targetRigidbody) {
return;
}
Quaternion deltaRotationDifference = transform.rotation * Quaternion.Inverse(controllerRotationSnapshot);
targetRigidbody.MoveRotation(targetRotationSnapshot * deltaRotationDifference);
}
It works perfectly as long as the target object is at a rotation of 0,0,0 (in euler angles). But the moment the target object is picked up with a different rotation at all (i.e. [X: 20, Y: -5, Z: 325] or something), the frame-by-frame controller difference (a 'delta rotation' I've heard this called?) gets applied on a completely different axis. It's very confusing because as far as I can tell, nothing about my code is applied locally, it's all using global calculations?
I've done a lot of Googlin' and can't find an answer at all, any help is greatly appreciated.
I have a very simple script that updates my orthographic camera on a given resolution so that it accurately scales the view to be pixel perfect.
Here is some relevant code:
OrthographicSetting get_override(int size)
{
return Overrides.FirstOrDefault(x => x.OrthographicSize == size);
}
void update_ortho()
{
m_last_size = Screen.height;
float ref_size = (OrthographicSize / PixelsPerUnit) * 0.5f;
OrthographicSetting or = get_override(m_last_size);
float ppu = or != null ? or.PixelsPerUnit : PixelsPerUnit;
float ortho_size = (m_last_size / ppu) * 0.5f;
float multiplier = Mathf.Max(1, Mathf.Round(ortho_size / ref_size));
ortho_size /= multiplier;
this.GetComponent<Camera>().orthographicSize = ortho_size;
Debug.Log(m_last_size + " " + ortho_size + " " + multiplier + " " + ppu);
}
[System.Serializable]
public class OrthographicSetting
{
public int OrthographicSize;
public float PixelsPerUnit;
}
OrthographicSetting get_override(int size)
{
return Overrides.FirstOrDefault(x => x.OrthographicSize == size);
}
With this, i can specify a set of overrides for every resolution.
My current setup is using 100 pixels per unity unit. All of my sprites use point filtering with no compression. Yet i still get strange results. 90% of the sprites render fine, but some seem to be rendering incorrectly.
Here's a screenshot to illustrate:
I may have solved the problem. I was using a sprite shader with pixel snap turned on. if i turn off pixel snap the problem seems to more or less go away. I still get the occasional problem with game objects that aren't in "nice" positions, i dunno how to avoid that problem though...