- Home /
Get 360-degree rotation in on-screen directional arrow?
Hi guys,
I have the following code for an on-screen directional arrow:
function OnGUI() {
target = GetClosestObject("Checkpoint", "Finish").transform;
if (target != null) { //Get the targets position on screen into a Vector3 targetPos = cam.WorldToScreenPoint (target.transform.position);
//Get the middle of the screen into a Vector3
screenMiddle = Vector3(Screen.width/2, Screen.height/2, 0);
//Compute the angle from screenMiddle to targetPos
var tarAngle = (Mathf.Atan2(targetPos.x-screenMiddle.x,Screen.height-targetPos.y-screenMiddle.y) * Mathf.Rad2Deg)+90;
//if (tarAngle < 0) tarAngle +=360;
//Calculate the angle from the camera to the target
var targetDir = target.transform.position - cam.transform.position;
var forward = cam.transform.forward;
var angle = Vector3.Angle(targetDir, forward);
//If the angle exceeds 90deg inverse the rotation to point correctly
if(angle<90)
{
transform.localRotation = Quaternion.Euler(-tarAngle,90,270);
}
else
{
transform.localRotation = Quaternion.Euler(tarAngle,270,90);
}
// Draw compass
var centre = Vector2(dialPos.x + arrow.width / 2, dialPos.y + arrow.height / 2);
var savedMatrix = GUI.matrix;
if (tarAngle != 0)
GUIUtility.RotateAroundPivot(angle, centre);
GUI.DrawTexture(Rect(centre.x - (arrow.width / 2), centre.y - (arrow.height / 2), arrow.width, arrow.height), arrow);
GUI.matrix = savedMatrix;
}
}
It appears to have something that forces it to always run the other way after rotating 180 degrees. Because of that, it points the opposite way from where it should point when the player is in some orientations relative to the target. The solution is to allow 360-degree rotation, but I'm not sure how to enable it. Any ideas?
MachCUBED
I edited the code to look like this:
function OnGUI() {
target = GetClosestObject("Checkpoint", "Finish").transform;
if (target != null) { //Get the targets position on screen into a Vector3 targetPos = cam.WorldToScreenPoint (target.transform.position);
//Get the middle of the screen into a Vector3
screen$$anonymous$$iddle = Vector3(Screen.width/2, Screen.height/2, 0);
//Compute the angle from screen$$anonymous$$iddle to targetPos
var tarAngle = ($$anonymous$$athf.Atan2(targetPos.x-screen$$anonymous$$iddle.x,Screen.height-targetPos.y-screen$$anonymous$$iddle.y) * $$anonymous$$athf.Rad2Deg);
//Calculate the angle from the camera to the target
var targetDir = target.transform.position - cam.transform.position;
var forward = cam.transform.forward;
var angle = Vector3.Angle(targetDir, forward);
// Draw compass
var centre = Vector2(dialPos.x + arrow.width / 2, dialPos.y + arrow.height / 2);
var saved$$anonymous$$atrix = GUI.matrix;
if (tarAngle != 0)
GUIUtility.RotateAroundPivot(angle, centre);
GUI.DrawTexture(Rect(centre.x - (arrow.width / 2), centre.y - (arrow.height / 2), arrow.width, arrow.height), arrow);
GUI.matrix = saved$$anonymous$$atrix;
}
}
And it still isn't rotating to the left side as needed. It's as if $$anonymous$$athf.Atan2 is always returning a positive value, and it needs to be set to negative if the target is to the left of the screen. What should I do?
I tried to rewrite my code using this answer as a guide: http://answers.unity3d.com/questions/177383/trying-to-build-2d-compass.html
And came up with this code:
function OnGUI() {
target = GetClosestObject("Checkpoint", "Finish").transform;
if (target != null)
{
var dirVector = target.transform.position - player.transform.position;
dirVector.y = 0; // remove the vertical component, if any
var rot = Quaternion.FromToRotation(player.transform.position, dirVector);
var angle: float; // angle is what we want
var axis: Vector3; // but an axis variable must be provided as well
angle = rot.eulerAngles.y;
// Draw compass
var centre : Vector2 = Vector2(dialPos.x + arrow.width / 2, dialPos.y + arrow.height / 2);
var saved$$anonymous$$atrix : $$anonymous$$atrix4x4 = GUI.matrix;
GUIUtility.RotateAroundPivot(angle, centre);
GUI.DrawTexture(Rect(centre.x - (arrow.width / 2), centre.y - (arrow.height / 2), arrow.width, arrow.height), arrow);
GUI.matrix = saved$$anonymous$$atrix;
}
}
It now rotates extremely slowly, with its rotation speed going up in unpredictable ways whenever I get close to a target. $$anonymous$$ore importantly, the arrow always points in a completely-different direction from where it should, and the result is that the code is even less useful than my old code. What am I doing wrong here?
$$anonymous$$achCUBED
Is this a 2D game? do you have a screenshot showing the setup? as I'm having trouble understanding what you are trying to achieve from reading your code. :) thanks, Scribe.
It's a 3d game. You can see an example screenshot (which shows the old code, not the code above) at http://twitpic.com/9r2drm
The arrow is supposed to target the closest hoop, and if I use the old code, it only points to the hoop if it's on the right of the player. This is because the old code doesn't appear to have 360-degree rotation capabilities.
I tried looking to http://8bitmemories.blogspot.com/2011/12/compass-in-unity3d.html for help, and implemented his Compass.cs script as per his instructions. The pip didn't move, so now it's back to the same old DirectionArrow script.