- Home /
Duplicate Question
Creating a kind of head-up radar display
Hi everyone, I've been trying for some hours to find a solution to this problem but I can't manage to...
What I want to design is a kind of head-up display : when the player approach some items (that are tagged) and has them on the screen, I want a Texture2D to appear on the screen in front of the item using the GUI.
But for now I just managed to count the items within a fixed distance that are in the screen (I don't want to care about the ones behind me for example). Now I want to add the Texture but I fail at it :(
I hope one of you may be able to find where is the problem !
Here's the script I use :
using UnityEngine;
using System.Collections;
public class GUIRadar : MonoBehaviour
{
public Texture2D RadarLock; //2D Texture of the radar square that msut go in front of the items
public GameObject Controller; //First person controller that gives the Horizontal rotation
public float[] radarWidth; //Radar square width and height on the GUI
public float[] radarHeight;
public float[] radarXPos; //Radar square position on the GUI ("in front" of the items)
public float[] radarYPos;
public float xPosCoef; //3 coefficients used to adjust the position and size of the radar square on the GUI
public float yPosCoef;
public float sizeCoef;
public float alphaX; //Angles between -the player looking direction and the "0"
public float betaX; // -the player->item ray and the "0"
public float deltaX; //The difference between those angles
public float alphaY; //Same here for vertical axis
public float betaY;
public float deltaY;
public float XviewingAngle; //Allowed angles to display the radar square
public float YviewingAngle; //i.e. : if the player looks too far away right from the item it's useless to display the square since it's out of the screen
private int itemsNumber; //Just a count of the directly visibles items
private string numberOfItems; //Same but in string format
private GameObject[] PossibleInteractionItems; //GameObject list to get all the items in view that got tagged
private RaycastHit hittedItem; //To colect information of the RayCast
private Ray ray; //To set the direction of the ray
void Awake()
{
itemsNumber=0;
PossibleInteractionItems=GameObject.FindGameObjectsWithTag(Tags.interact); //I collect every items with the wanted tag
}
private void OnGUI()
{
//--------------------THIS THING DOESN'T WORK
for(int i=0;i<itemsNumber;i++)
{
GUI.DrawTexture(new Rect(Screen.width/2-radarWidth[i]/2,Screen.height/2-radarHeight[i]/2,radarWidth[i],radarHeight[i]),RadarLock);
}
//----------------------
GUI.Label(new Rect(Screen.width/2+50,Screen.height/2,50,50),numberOfItems);
}
void Update()
{
itemsNumber=0; //At each frame I set everything to 0
radarWidth=null;
radarHeight=null;
radarXPos=null;
radarYPos=null;
foreach(GameObject item in PossibleInteractionItems) //For each tagged item
{
if(Vector3.Distance(transform.position,item.transform.position) < 5f) //if the item's distance is under 5
{
ray=new Ray(transform.position,new Vector3(item.transform.position.x-transform.position.x,item.transform.position.y-transform.position.y,item.transform.position.z-transform.position.z)); //I set the Ray direction : from my player to the item
betaX=Mathf.Abs(Mathf.Atan(ray.direction.x/ray.direction.z)/(2*Mathf.PI)*360); //I collect every angles informations
if(ray.direction.x<0)
betaX=-1*betaX;
if(ray.direction.x>0 && ray.direction.z<0)
betaX=180-betaX;
if(ray.direction.x<0 && ray.direction.z<0)
betaX=-180-betaX;
alphaX=Controller.transform.eulerAngles.y;
if(alphaX>180)
alphaX-=360;
deltaX=betaX-alphaX;
betaY=Mathf.Abs(Mathf.Atan(ray.direction.z/ray.direction.y)/(2*Mathf.PI)*360-90);
if(ray.direction.y>0)
betaY=180-betaY;
else
betaY=-1*betaY;
alphaY=-transform.eulerAngles.x;
if(alphaY<-180)
alphaY+=360;
deltaY=betaY-alphaY;
if(Mathf.Abs(deltaX)<XviewingAngle && Mathf.Abs(deltaY)<YviewingAngle) //and check if the item is in the screen
{
Debug.DrawRay (transform.position,ray.direction,Color.red,0.001f); //for debugging purposes ^^
Physics.Raycast(ray, out hittedItem);
if(hittedItem.collider.gameObject.tag == Tags.interact) //If the item is in direct view (not behind another obstacle)
{
//-------------------THIS DOESN'T WORK TOO
radarXPos[itemsNumber]=deltaX*xPosCoef;
radarYPos[itemsNumber]=deltaY*yPosCoef;
radarWidth[itemsNumber]=(Vector3.Distance (item.transform.position,transform.position))*sizeCoef;
radarHeight[itemsNumber]=(Vector3.Distance (item.transform.position,transform.position))*sizeCoef;
//-----------------------
itemsNumber++; //But this work : I got the right amount of items in the screen with a distance under 5
}
}
}
}
numberOfItems=itemsNumber.ToString(); //To display it in the OnGUI()
}
}
Ok, thanks so much for your help (I guess this was a huge block to read :P) About the fact that it could be done much simpler I guess I can only agree with you ! I just wanted to train myself thinking in 3D space (for example about angles and distance I'm pretty sure some Vector3D functions can do the work automatically ^^
I'll take a look at what you told be about converting World coordinate into GUI ones and I'll be back asap ;)
A applaud you getting a feel for 3D space. There are however some gotcha's associated with some of what you are doing... particularly with reading individual eulerAngle values and expecting them to be something specific.
robert dude! there is no apostrophe on a plural like gotchyas.
Well I succeed in getting how to convert World point into Screen one : that's pretty amazing pre-made tools that we've got there :P
I guess the problem I have now comes from my use of the lists : when I have 2 or more items in range the game stops and the error is given at the lines where I try to access radarXPos[itemsNumber] and tells me the array index is out of range.
But I guess I can manage to solve this on my own !
Anyway thank you very much for your help : you made me discover something new and really helpful for my future projects ;)
Answer by robertbu · May 13, 2013 at 02:41 PM
I think you are doing a whole lot of work here that could be done much simpler, but it would take more understanding of your game and this code to advise you on that simplification. But in terms of your question, one problem I see is that, you are calculating radarWidth and radarHeight in world coordinates but you are attempting to use them as GUI coordinates. There are four coordinate systems used in Unity: GUI, Screen, World, and Viewport. You can use the Camera class and the GUIUtility class to convert between them.
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Erroe when resizing GUITextures in C# file 1 Answer
How to get a pop-up window floating next to a gameobject? 1 Answer