- Home /
The question is answered, right answer was accepted
Aircraft altimeter
This is the problem.
I'm trying to create an altimeter to my aircraft, and I've decided to do it by a plane attached to the camera (instead of GUI so I could rotate the needles).
Everything is working fine if I fly straight and pull up.
However, as soon as I start rolling, my needles are rolling too to the other side. or if I bank, my needles start to turn and change in so many directions.
I've placed this script in order to make them stay in put:
var thousands : Transform; //this is for the thousands needle
var hundreds : Transform; //this is for the hundreds needle
var aircraft : Transform; //this is for the aircraft altitude
function LateUpdate () {
var hundredsZ = Quaternion.Euler(0,0, -(aircraft.position.y % 1000) *0.36);
//It rotates like a needle in a clock.
var thousandsZ = Quaternion.Euler(0,0, -(aircraft.position.y / 10) *0.36);
//yet again, slower for the thousands.
hundreds.rotation = hundredsZ;
thousands.rotation = thousandsZ;
}
However, setting x,y as zero always doesn't affect anything... I've tried to change the rotation directly, or eulerAngles, nothing helps.. any solution?
Answer by aldonaletto · Jul 05, 2012 at 04:49 AM
Don't use a plane - use OnGUI and the function GUIUtility.RotateAroundPivot to rotate the image (not feasible with GUITexture!):
var aircraft : Transform; var controlPanel : Texture2D; // control panel image var thousands : Texture2D; // thousands needle image var hundreds : Texture2D; // hundreds needle image var relativeCenter: Vector2; // altimeter center relative to the control panel
private var rPanel: Rect; private var rThousands: Rect; private var rHundreds: Rect; private var center: Vector2;
function Start(){ var w = controlPanel.width; var h = controlPanel.height; // rPanel centered horizontally, aligned to the screen bottom: rPanel = Rect((Screen.width-w)/2, Screen.height-h, w, h); // calculate altimeter center relative to the screen; center.x = rPanel.left+relativeCenter.x; center.y = rPanel.top+relativeCenter.y; // calculate rectangle for thousands needle w = thousands.width; h = thousands.height; rThousands = Rect(center.x-w/2, center.y-h/2, w, h); // calculate rectangle for hundreds needle w = hundreds.width; h = hundreds.height; rHundreds = Rect(center.x-w/2, center.y-h/2, w, h); }
function OnGUI(){ GUI.DrawTexture(rPanel, controlPanel); var hundredsZ = aircraft.position.y % 1000 0.36; // calculate hundreds angle var thousandsZ = aircraft.position.y / 10 0.36; // calculate thousands angle var saveMatrix = GUI.Matrix; // save current GUI.Matrix GUIUtility.RotateAroundPivot(thousandsZ, center); // set the rotated matrix GUI.DrawTexture(rThousands, thousands); // draw thousands needle rotated GUI.Matrix = saveMatrix; // restore unrotated matrix GUIUtility.RotateAroundPivot(hundredsZ, center); // set rotated matrix GUI.DrawTexture(rHundreds, hundreds); // draw hundreds needle over thousands needle GUI.Matrix = saveMatrix; // restore the original matrix }
NOTE: The needle images must be transparent squares with the needle centered at the image center (the images will be rotated around their centers).
Thank a lot for your answer! This is exactly what I need. I have a question now, what does GUI.$$anonymous$$atrix = save$$anonymous$$atrix; actually does? you wrote it's "restore unrotated matrix", why would I want to restore an unrotated matrix? I want it to keep the rotation.
When you use RotateAroundPivot, Unity modifies the matrix that maps the GUI space in the screen, and anything you draw afterwards will have the same rotation relative to the original screen. You draw the first handle, then restore the matrix and use RotateAroundPivot to define the rotation of the second handle - if the matrix isn't restored, the new rotation is added to the previous one, giving incorrect results. I don't know if OnGUI always starts with a non-rotated matrix, so the matrix is again restored after drawing the second handle in order to avoid possible problems.
I see, so unity3D doesn't actually offer a way to rotate GUI, it's a trick someone came up with. cool :)
and if I can use you for one last question (.. ^^) your center formula didn't work out, I had to used many variables and factors in order to put the GUI in the middle.
Is there a formula which no matter what's the resolution screen is, it would stay the same?
The center variable actually was supposed to be set manually to the center of the altimeter in the Inspector - but you're right: this method doesn't work for different screen sizes.
A simple alternative is to have a texture showing the whole control panel, and express the altimeter center relative to the top-left corner of this image - I changed my answer to include this control panel texture and the calculations to make it horizontally centered and aligned to the bottom of the screen: you must define relativeCenter in the Inspector, and it will keep the needles at the same position relative to the panel.
But this alternative doesn't change the control panel size, thus in a big resolution it will become $$anonymous$$uscule, and too big at low resolutions. The alternative to fix this is to set the GUI.matrix to a scale proportional to the vertical resolution before drawing anything else:
function OnGUI(){
GUI.matrix = $$anonymous$$atrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one * Screen.height/originalHeight);
var save$$anonymous$$atrix = GUI.matrix;
...
where originalHeight is the screen height you're using to develop the game - this way the panel will look the same in any resolution.
Answer by Seth-Bergman · Jul 05, 2012 at 04:17 AM
If I understand correctly, you only want the needle to rotate on one axis. So maybe something like:
if(transform.rotation.z < (aircraft.position.y % 1000))
transform.Rotate(0,0,1);
if(transform.rotation.z > (aircraft.position.y % 1000))
transform.Rotate(0,0,-1);
of course the rotation would be 0-360, so you'd need to adjust for that.. also, might need transform.localRotation, now that I think of it
Follow this Question
Related Questions
Rotation on Android vs. PC 0 Answers
Camera Script Rolling on the Z 3 Answers
Unable to set Rotation 1 Answer
Steering using Quarternion.LookRotation. 0 Answers