n00b question and I don't even understand enough to be able to Google well (or understand the answers appropriately).
I'm exploring Unity 3D and playing with Gyroscope input The issue is that each axis of the gyro returns values between -1 and +1 with 0 being the devices orientation when the gyro is enabled, where +1 & -1 share a border (like 12 on a clockface). However, the gyro's 0,0,0 point is not being reset when the gyro is enabled. The unity forums suggest deactivating the then re-activating the gyro will help - it doesn't.
In effect the gyro's 0 point is static in the current version of iOS & Unity, which means I need to 'offset' it to take into account the phone's starting position.
My plan was to have something like:
var GyroOffset : Quaternion;
var CurrentGyroAttitude : Quaternion;
var DeadSpotXPos : float;
var DeadSpotXPos : float;
var ThresholdPos : float;
var ThresholdNeg : float;
function Start() {
Input.gyro.enabled = true;
Input.gyro.UpdateInterval = 0.001;
GyroOffset = Input.gryo.attitude;
}
function Update() {
CurrentGyroAttitude = input.gyro.attitude - GyroOffset;
if (CurrentGyroAttitude.x > ThresholdPos) DoSomething(1);
if (CurrentGyroAttitude.x < ThresholdNeg) DoSomething(-1);
if (CurrentGyroAttitude.x > DeadSpotXPos &&
CurrentGyroAttitude.X < ThresholdPos) DoSomethingElse(1);
if (CurrentGyroAttitude.x < DeadSpotXNeg &&
CurrentGyroAttitude.x < ThresholdNeg) DoSomethingElse(-1);
}
* Where DoSomething(arbitraryFloat) and DoSomethingElse(anotherArbitraryFloat) does things that I want done and arbitrary float is not related to Gyro output.
As the Gyro output is between -1 and +1, we could reach a case where CurrentGyroAttitude.x could legitimately be -2 or +2. The problem with this plan is that I have to "offset" to my thresholds & deadspots as well which becomes "not neat" for tuning purposes. I'd much rather only manipulate the CurrentGyroAttitude.
However, I don't know how to do "clock face arthematic" in UnityScript. I think I'm talking about modulus mathematics but I keep running into complex mathematics about crypto that's doing my head in. :)
Can anyone walk me through "cleaning" the gyro attitude output so that my clean output stays between -1 and +1, once 'offset' has been taken into effect?
Incidentally if anyone can shed light on Unity's GyroUpdateInterval that would be awesome because the documentation doesn't explain what the updates are measured in, or what the effect of manipulating is.
I don't suppose you really wanted to access members of the Quaternion - they don't work the way you think they do. What you wanted was Quaternion.eulerAngles.
To make the angle relative to the starting position modify your Update:
Vector3 CurrentGyroEuler=(Quaternion.Inverse(Input.gyro.attitude)* GyroOffset).eulerAngles
Related
I am currently working with the accelerometer on Android, and have run into an interesting situation. I need to find out the maximum values for the following, WITHOUT requiring the end user to flop their phone around in some elaborate calibration routine. The values I am looking for specifically are...
#Override
public void onSensorChanged(SensorEvent event) {
SensorManager.getOrientation(outR, xyz);
float X, Y, XMax, YMax;
X = xyz[1];
Y = xyz[2];
XMax = ???;
YMax = ???;
}
I've poked around online, but have not had much luck determining what the values would be (it appears it changes from phone to phone), nor seen anyone mention a way to pull that value from somewhere.
Does anyone know how I might determine the maximum/minimum values of xyz[1] and xyz[2]?
UPDATE: An Example of what I mean is the following:
When I report directly the outputed float from xyz[1], and then move my phone forward and backward all the way, I get the following results:
min value it reports: -1.50 (give or take a 10ths)
max value it reports: 1.50 (give or take a 10ths)
when I roll my phone left and right, I get the following for xyz[2]:
min value it reports: -3.14 (give or take a 10ths)
max value it reports: 3.14 (give or take a 10ths)
I was told this changes between phones, however this could be wrote.
I don't know what max/min values you're talking about but getOrientation will populate a vector with the following data:
xyz[0]: azimuth [-π,π]
xyz[1]: pitch [-π,π]
xyz[2]: roll [-π/2,π/2]
From docs:
All three angles above are in radians and positive in the
counter-clockwise direction.
Refer also to the SensorManager.java:1094 class:
https://android.googlesource.com/platform/frameworks/base/+/b267554/core/java/android/hardware/SensorManager.java
I try to create game for Android and I have problem with high speed objects, they don't wanna to collide.
I have Sphere with Sphere Collider and Bouncy material, and RigidBody with this param (Gravity=false, Interpolate=Interpolate, Collision Detection = Continuous Dynamic)
Also I have 3 walls with Box Collider and Bouncy material.
This is my code for Sphere
function IncreaseBallVelocity() {
rigidbody.velocity *= 1.05;
}
function Awake () {
rigidbody.AddForce(4, 4, 0, ForceMode.Impulse);
InvokeRepeating("IncreaseBallVelocity", 2, 2);
}
In project Settings I set: "Min Penetration For Penalty Force"=0.001, "Solver Interation Count"=50
When I play on the start it work fine (it bounces) but when speed go to high, Sphere just passes the wall.
Can anyone help me?
Thanks.
Edited
var hit : RaycastHit;
var mainGameScript : MainGame;
var particles_splash : GameObject;
function Awake () {
rigidbody.AddForce(4, 4, 0, ForceMode.Impulse);
InvokeRepeating("IncreaseBallVelocity", 2, 2);
}
function Update() {
if (rigidbody.SweepTest(transform.forward, hit, 0.5))
Debug.Log(hit.distance + "mts distance to obstacle");
if(transform.position.y < -3) {
mainGameScript.GameOver();
//Application.LoadLevel("Menu");
}
}
function IncreaseBallVelocity() {
rigidbody.velocity *= 1.05;
}
function OnCollisionEnter(collision : Collision) {
Instantiate(particles_splash, transform.position, transform.rotation);
}
EDITED added more info
Fixed Timestep = 0.02 Maximum Allowed Tir = 0.333
There is no difference between running the game in editor player and on Android
No. It looks OK when I set 0.01
My Paddle is Box Collider without Rigidbody, walls are the same
There are all in same layer (when speed is normal it all works) value in PhysicsManager are the default (same like in image) exept "Solver Interation Co..." = 50
No. When I change speed it pass other wall
I am using standard cube but I expand/shrink it to fit my screen and other objects, when I expand wall more then it's OK it bouncing
No. It's simple project simple example from Video http://www.youtube.com/watch?v=edfd1HJmKPY
I don't use gravity
See:
Similar SO Question
A community script that uses ray tracing to help manage fast objects
UnityAnswers post leading to the script in (2)
You could also try changing the fixed time step for physics. The smaller this value, the more times Unity calculates the physics of a scene. But be warned, making this value too small, say <= 0.005, will likely result in an unstable game, especially on a portable device.
The script above is best for bullets or small objects. You can manually force rigid body collisions tests:
public class example : MonoBehaviour {
public RaycastHit hit;
void Update() {
if (rigidbody.SweepTest(transform.forward, out hit, 10))
Debug.Log(hit.distance + "mts distance to obstacle");
}
}
I think the main problem is the manipulation of Rigidbody's velocity. I would try the following to solve the problem.
Redesign your code to ensure that IncreaseBallVelocity and every other manipulation of Rigidbody is called within FixedUpdate. Check that there are no other manipulations to Transform.position.
Try to replace setting velocity directly by using AddForce or similar methods so the physics engine has a higher chance to calculate all dependencies.
If there are more items (main player character, ...) involved related to the physics calculation, ensure that their code runs in FixedUpdate too.
Another point I stumbled upon were meshes that are scaled very much. Having a GameObject with scale <= 0.01 or >= 100 has definitely a negative impact on physics calculation. According to the docs and this Unity forum entry from one of the gurus you should avoid Transform.scale values != 1
Still not happy? OK then the next test is starting with high velocities but no acceleration. At this phase we want to know, if the high velocity itself or the acceleration is to blame for the problem. It would be interesting to know the velocities' values at which the physics engine starts to fail - please post them so that we can compare them.
EDIT: Some more things to investigate
6.7 m/sec does not sound that much so that I guess there is a special reason or a combination of reasons why things go wrong.
Is your Maximum Allowed Timestep high enough? For testing I suggest 5 to 10x Fixed Timestep. Note that this might kill the frame rate but that can be dfixed later.
Is there any difference between running the game in editor player and on Android?
Did you notice any drops in frame rate because of the 0.01 FixedTimestep? This would indicate that the physics engine might be in trouble.
Could it be that there are static colliders (objects having a collider but no Rigidbody) that are moved around or manipulated otherwise? This would cause heavy recalculations within PhysX.
What about the layers: Are all walls on the same layer resp. are the involved layers are configured appropriately in collision detection matrix?
Does the no-bounce effect always happen at the same wall? If so, can you just copy the 1st wall and put it in place of the second one to see if there is something wrong with this specific wall.
If not to much effort, I would try to set up some standard cubes as walls just to be sure that transform.scale is not to blame for it (I made really bad experience with this).
Do you manipulate gravity or TimeManager.timeScale from within a script?
BTW: are you using gravity? (Should be no problem just
I want to develop app to calculate Sound frequency in Android. Android Device will take
Sound from microphone (i.e. out side sound) and I have one color background screen in app.
on sound frequency changes i have to change background color of screen .
So my question is "How can i get sound frequency"?
is there any android API available?
Please help me out of this problem.
Your problem was solved here EDIT: archived here. Also you can analyze the frequency by using FFT.
EDIT: FFTBasedSpectrumAnalyzer (example code, the link from the comment)
Thanks for Reply I have done this by using sample on
http://som-itsolutions.blogspot.in/2012/01/fft-based-simple-spectrum-analyzer.html
Just modify your code for to calculate sound frequency by using below method
// sampleRate = 44100
public static int calculate(int sampleRate, short [] audioData){
int numSamples = audioData.length;
int numCrossing = 0;
for (int p = 0; p < numSamples-1; p++)
{
if ((audioData[p] > 0 && audioData[p + 1] <= 0) ||
(audioData[p] < 0 && audioData[p + 1] >= 0))
{
numCrossing++;
}
}
float numSecondsRecorded = (float)numSamples/(float)sampleRate;
float numCycles = numCrossing/2;
float frequency = numCycles/numSecondsRecorded;
return (int)frequency;
}
The other answers show how to display a spectrogram. I think the question is how to detect a change in fundamental frequency. This is asked so often on Stack Exchange I wrote a blog entry (with code!) about it:
http://blog.bjornroche.com/2012/07/frequency-detection-using-fft-aka-pitch.html
Admittedly, the code is in C, but I think you'll find it easy to port.
In short, you must:
low-pass the input signal so that higher frequency overtones are not mistaken for the fundamental frequency (this may not appear to be an issue in your application, since you are just looking for a change in pitch, but I recommend doing it anyway for reasons that are too complex to go into here).
window the signal, using a proper windowing function. To get the most responsive output, you should overlap the windows, which I don't do in my sample code.
Perform an FFT on the data in each window, and calculate the frequency using the index of maximum absolute peak value.
Keep in mind for your application where you probably want to detect the change in pitch accurately and quickly, the FFT method I describe may not be sufficient. You have two options:
There are techniques for increasing the specificity of the pitch tracking using phase information, not just the absolute peak.
Use a time-domain method based on autocorrelation. Yin is an excellent choice. (google for "yin pitch tracking")
Here is a link to the code mentioned. There's also some other useful code there.
https://github.com/gast-lib/gast-lib/blob/master/library/src/root/gast/audio/processing/ZeroCrossing.java
Here's the deal with ZeroCrossings:
It is inaccurate at determining frequency precisely based on recorded audio on an Android. That said, it is still useful for giving your app a general sense that the sound it is hearing is a constant singing tone, versus just noise.
The code here seems to work quite well for determining frequency, (if you can translate it from C# to java)
http://code.google.com/p/yaalp/
I am currently developing a game for Android, and I would like your expertise on an issue that I have been having.
Background:
My game incorporates frame rate independent motion, which takes into
account the delta time value before performing necessary Velocity
calculations.
The game is a traditional 2D platformer.
The Issue:
Here's my issue (simplified). Let's pretend that my character is a square standing on top of a platform (with "gravity" being a constant downward velocity of characterVelocityDown).
I have defined the collision detection as follows (assuming Y axis points downwards):
Given characterFootY is the y-coordinate of the base of my square character, platformSurfaceY is the upper y-coordinate of my platform, and platformBaseY is the lower y-coordinate of my platform:
if (characterFootY + characterVelocityDown > platformSurfaceY && characterFootY + characterDy < platformBaseY) {
//Collision Is True
characterFootY = platformSurfaceY;
characterVelocityDown = 0;
} else{
characterVelocityDown = deltaTime * 6;
This approach works perfectly fine when the game is running at regular speed; however, if the game slows down, the deltaTime (which is the elapsed time between the previous frame and the current frame) becomes large, and characterFootY + characterVelocityDown exceed the boundaries that define collision detection and the character just falls straight through (as if teleporting).
How should I approach this issue to prevent this?
Thanks in advance for your help and I am looking forward to learning from you!
What you need to do is to run your physics loop with constant delta time and iterate it as many time as it need with current tick.
const float PHYSICS_TICK = 1/60.f; // 60 FPS
void Update( float dt )
{
m_dt += dt;
while( m_dt > PHYSICS_TICK )
{
UpdatePhysics( PHYSICS_TICK );
m_dt -= PHYSICS_TICK;
}
}
There are various technics used to handle the tick left ( m_dt )
Caps for miniumum tick and maximum tick are also a must.
I guess the issue here is that slowdowns are inevitable. You can try and optimize the code but you'll always have users with slow devices or busy sections of your game where it takes a little longer than usual to process it all. Instead of assuming a consistent delta, assume the opposite. Code under the realization that someone could try installing it on an abacus.
So basically, as SeveN says, make your game loop handle slowdowns. The only real way to do this (in my admittedly limited experience) would be to place a cap on how large delta can be. This will result in your clock not running on time exactly, but when you think about it, that's how most games handle slowdown. You don't fire up StarCraft on your pentium 66 and have it run at 5 FPS but full speed, it slow down and processes it as normal, albeit at a slideshow.
If you did such a thing, during periods of slowdown in your game, it'd visibly slow down... but the calculations should still all be spot on.
edit: just realised you're SeveN. Well done.
I am making a 2d game. The phone is held horizontally and a character moves up/down & left/right to avoid obstacles. The character is controlled by the accelerometer on the phone. Everything works fine if the player doesn't mind (0,0) (the point where the character stands still) being when the phone is held perfectly flat. In this scenario it's possible to just read the Y and X values directly and use them to control the character. The accelerometer values are between -10 and 10 (they get multiplied by an acceleration constant to decide the movement speed of the character), libgdx is the framework used.
The problem is that having (0,0) isn't very comfortable, so the idea is to calibrate it so that 0,0 will be set to the phones position at a specific point in time.
Which brings me to my question, how would I do this? I tried just reading the current X and Y values then subtracting it. The problem with that is that when the phone is held at a 90 degree angle then the X offset value is 10 (which is the max value) so it ends up becoming impossible to move because the value will never go over 10 (10-10 = 0). The Z axis has to come into play here somehow, I'm just not sure how.
Thanks for the help, I tried explaining as best as I can, I did try searching for the solution, but I don't even know what the proper term is for what I'm looking for.
An old question, but I am providing the answer here as I couldn't find a good answer for Android or LibGDX anywhere. The code below is based on a solution someone posted for iOS (sorry, I have lost the reference).
You can do this in three parts:
Capture a vector representing the neutral direction:
Vector3 tiltCalibration = new Vector3(
Gdx.input.getAccelerometerX(),
Gdx.input.getAccelerometerY(),
Gdx.input.getAccelerometerZ() );
Transform this vector into a rotation matrix:
public void initTiltControls( Vector3 tiltCalibration ) {
Vector3.tmp.set( 0, 0, 1 );
Vector3.tmp2.set( tiltCalibration ).nor();
Quaternion rotateQuaternion = new Quaternion().setFromCross( Vector3.tmp, Vector3.tmp2 );
Matrix4 m = new Matrix4( Vector3.Zero, rotateQuaternion, new Vector3( 1f, 1f, 1f ) );
this.calibrationMatrix = m.inv();
}
Whenever you need inputs from the accelerometer, first run them through the rotation matrix:
public void handleAccelerometerInputs( float x, float y, float z ) {
Vector3.tmp.set( x, y, z );
Vector3.tmp.mul( this.calibrationMatrix );
x = Vector3.tmp.x;
y = Vector3.tmp.y;
z = Vector3.tmp.z;
[use x, y and z here]
...
}
For a simple solution you can look at the methods:
Gdx.input.getAzimuth(), Gdx.input.getPitch(), Gdx.input.getRoll()
The downside is that those somehow use the internal compass to give your devices rotation compared to North/South/East/West. I did only test that very shortly so I'm not 100% sure about it though. Might be worth a look.
The more complex method involves some trigonometry, basically you have to calculate the angle the phone is held at from Gdx.input.getAccelerometerX/Y/Z(). Must be something like (for rotation along the longer side of the phone):
Math.atan(Gdx.input.getAccelerometerX() / Gdx.input.getAccelerometerZ());
For both approaches you then store the initial angle and subtract it later on again. You have to watch out for the ranges though, I think Math.atan(...) is within -Pi and Pi.
Hopefully that'll get you started somehow. You might search for "Accelerometer to pitch/roll/rotation" and similar, too.