HUD Radar hoping this could help anyone

Well after working during two days on it (yeah i’m new to Unity so maybe some of you may be able to achieve this in an hour :p), I finally ended doing something good that works well !

My project was to create a kind of HUD (Head-Up Display) that could focus items in your scene (for me the items you can interact with).
I have to warn you that I still guess I’ve done some things in a weird way so they could have been much simpler !

Anyway thanks to robertbu for his help and here’s my script (that I fully commented for more understanding) if it can be useful to any future visitor : Feel free to use on your own :wink:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;				//Use this so you can manipulate Lists

public class GUIRadar : MonoBehaviour
{
	public Texture2D targetIcon;				//The target icon that will be placed in front of targets
	public float maxTargetIconSize = 300f;		//The maximum size of icons when close to the target
	public float minTargetIconSize = 0f;		//The minimum size of icons when they appear (far from the target)
	public float maxDistanceDisplay = 10f;		//The maximum distance from where you can see the icons appearing
	public float minDistanceDisplay = 2f;		//The minimum distance from where you see the icons disappearing when too close
	public float smoothGrowingParameter = 25f;	//The speed of the growing effect on icons
	public float smoothMovingParameter = 25f;	//The moving speed of items : high values means the icon is "attached" to the item
	public bool directViewEnabled = true;		//If you want to allow icon display even if targets aren't in direct view for the player
	
	public struct TargetStruct					//Structure that contain every icon informations
	{
		public GameObject item;					//-the item the icon is linked to
		public Vector3 screenPos;				//-the screen position of the icon (!= world position)
		public float xSize, ySize;				//-the current size of the icon on the screen
		public float xPos, yPos;				//-the current coordinates of the screen position
		public float xTargetSize, yTargetSize;	//-the coordinates you want the icon to reach
		public float xTargetPos, yTargetPos;	//-the size you want the icon to reach on the screen
		public float distance;					//-the distance between player and the item linked to the icon
		public bool directView;					//-tells you if the item is in direct view or not
	}
	
	public List<TargetStruct> TargetList = new List<TargetStruct>();//Your ICONS LIST
	public GameObject[] Targets;									//The GameObjects considered as targets
	
	private int targetsCount;										//Number of targets in the scene
	
	void Awake()														
	{
		Targets = GameObject.FindGameObjectsWithTag(/**/Tags.interact/**/);		//Get all the potential targets in the scene (just replace it by your own tag : "MyTag")
		
		foreach(GameObject target in Targets)									//Put every detected GameObject into your ICONS LIST
		{
			TargetStruct newTarget = new TargetStruct();
			newTarget.item = target;											//and attach each icon its GameObject
			TargetList.Add(newTarget);
		}
		
		targetsCount = TargetList.Count;										//Count the number of target in the scene
	}
	
	void Update()
	{		
		for(int i = 0; i<targetsCount; i++)															//You have to repeat it for every icons : be aware that if you have too much that could use a lot of ressoures 
		{
			TargetStruct target = new TargetStruct();												//You have to create a temporary TargetStruct since you can't access a variable of an element in a list directly
			target = TargetList[i];																	//You take the item attached to the icon
			
			target.screenPos = camera.WorldToScreenPoint(target.item.transform.position);			//Convert world coordinates of the item into screen ones
			target.distance = Vector3.Distance(target.item.transform.position, transform.position);	//Get the distance between item and player
			
			if(target.distance>maxDistanceDisplay || target.distance<minDistanceDisplay)			//If the item is too far or too close
			{
				target.xTargetSize = minTargetIconSize;												//you want it to disappear
				target.yTargetSize = minTargetIconSize;												//or at least to be in its smaller size
			}
			else
			{
				target.xTargetSize = maxTargetIconSize/(target.distance);							//Else you get its size with the
				target.yTargetSize = maxTargetIconSize/(target.distance);							//distance : far<=>small / close<=>big
				
			}
		
			if(target.distance>maxDistanceDisplay)													//If the item is too far, you set its screen position : (this way it seems as if the icon was coming away from the screen to focus your target)
			{
				if(target.screenPos.x<Screen.width/2)												//-if it's under the center of the view field
					target.xTargetPos = 0;															//to the bottom of the screen
				else 																				//-else
					target.xTargetPos = Screen.width;												//to the top of the screen
				
				if(target.screenPos.y<Screen.height/2)												//-if it's on the right of the view field
					target.yTargetPos = Screen.height;												//to the right of the screen
				else 																				//-else
					target.yTargetPos = 0;															//to the left of the screen
			}
			else 																					//If the item is NOT too far, you set its screen position :
			{
				target.xTargetPos = target.screenPos.x-target.xSize/2;								//in x-axis to the item's x-position minus half of the icon's size
				target.yTargetPos = Screen.height-target.screenPos.y-target.ySize/2;				//in y-axis to the item's y-position minus half of the icon's size
			}
			
			target.xSize = Mathf.Lerp(target.xSize, target.xTargetSize, smoothGrowingParameter*Time.deltaTime);	//You do lerps on your icons size so you can adjust
			target.ySize = Mathf.Lerp(target.xSize, target.yTargetSize, smoothGrowingParameter*Time.deltaTime);	//the speed of their resizing
			
			target.xPos = Mathf.Lerp(target.xPos, target.xTargetPos, smoothMovingParameter*Time.deltaTime);		//You do lerps on your icons position so you can adjust
			target.yPos = Mathf.Lerp(target.yPos, target.yTargetPos, smoothMovingParameter*Time.deltaTime);		//their moving speed
			
			RaycastHit hitInfos = new RaycastHit();																	//You create a new variable to stock the information of the coming raycast
			Physics.Raycast(transform.position, target.item.transform.position-transform.position, out hitInfos);	//and you RayCast from the player's position to the item's position
			
			if(hitInfos.collider.gameObject.layer==8)																//HERE IS A BIT TRICKY : you have to creat new layers (I called them "Interactive Items" and "Obstacles") and to apply them to your various items.
				target.directView=true;																				//Then you select EVERY items in your scene and set their layer to "Ignore Raycast". After that you select your interactive items biggest shape (if you have big trigger colliders on them select the item that hold it),
			else 																									//and set their layers to "Interactive Items". Last part is setting every potential obstacle item layer to "Obstacles".
				target.directView=false;																			//NOTE : Here my "Interactive Items" layer number is 8
			
			TargetList[i] = target;																	//You apply all the variables to your index-i icon in the ICONS LIST
		}
	}
	
	void OnGUI()
	{
		for(int i = 0; i<targetsCount; i++)																								//For every icon
		{
			if(TargetList[i].screenPos.z>0  (!directViewEnabled || (directViewEnabled  TargetList[i].directView)))					//If the icon is in front of you and all the required conditions are okay
				GUI.DrawTexture(new Rect(TargetList[i].xPos, TargetList[i].yPos, TargetList[i].xSize, TargetList[i].ySize), targetIcon);//you display the icon with it's size and position
		}
	}
}

And here’s a quick screen of the in-game appearance :

This looks to be exactly what I need … Thx a stack … busy trying to implement … do you maybe have a demo scene handy?

Well first I’m glad this is finally usefull to someone :smile:

Here’s a quick demo scene I just made to show how the script works in game (note that you can adjust a lot of parameters such as the moving speed of the cursor, its size, …)

You can download it here. Enjoy ! :wink:

Hi

Dunno if you still check here, but I have some questions.

This looked to be what I was after, and I got it to work ok but not in the way I need.

I am using it to target enemies, or at least show me their position, but then I destroy one of things it is targeting. This is where it goes wrong! Once the object has been destroyed, the target icons for it remains frozen on the screen, along with all the others that were being targeted.
How would I go about removing the destroyed objects icon, leaving the others intact?

The other thing, is I am wanting to use the icons on a forward and rear scanner, so I can get my bearings when looking for the targets. I have 2 scanner cameras, 1 in each top corner, and the script attached to both. My problem here is, if I rotate to face the other way, the icons drop off the camera and onto the main screen.

Any idea what I have to do here?

Cheers,
John

Well yes I’m still checking here to look for some improvements I could add to my script.

I’m currently working on the two things you mentionned:

  • the update problem where the icon stayed on the UI has already been solved with a new function added to the code.
  • I found a way to bypass the problem you had using multiple cameras and I’m still scripting it: it should be done soon.

I’ll post my result asap. with a new version of the demo scene so you’ll get how to use the new features.

First sorry for this being a double post but here you go :

  • now you can call the DeleteTarget method from the radar script in order to suppress an item from the icons (this solves the first problem you had). Make sure to call this before destroying your GameObject since one of the method parameter is the item tagged with the RadarDetectable (or anything else now :wink: ) tag.
  • also, th script now takes into consideration the viewport of the camera it’s attached to and I added an alpha blending option in order to get the icons going from 1.0 alpha scale in the middle of the viewport to 0.0 on the edges. This way the icons kinda disapear when going otside of the viewport (note that you can adjust the effect with the alphaStartPercentage parameter).
using UnityEngine;
using System.Collections;
using System.Collections.Generic;                //Use this so you can manipulate Lists

public class GUIRadarTest : MonoBehaviour
{
    [SerializeField] private Texture2D targetIcon;                    //The target icon that will be placed in front of targets
    [SerializeField] private float maxTargetIconSize = 300f;        //The maximum size of icons when close to the target
    [SerializeField] private float minTargetIconSize = 0f;            //The minimum size of icons when they appear (far from the target)
    [SerializeField] private float maxDistanceDisplay = 10f;        //The maximum distance from where you can see the icons appearing
    [SerializeField] private float minDistanceDisplay = 2f;            //The minimum distance from where you see the icons disappearing when too close
    [SerializeField] private float smoothGrowingParameter = 25f;    //The speed of the growing effect on icons
    [SerializeField] private float smoothMovingParameter = 25f;        //The moving speed of items : high values means the icon is "attached" to the item
    [SerializeField] private string tagToFollow = "RadarDetectable";
    [SerializeField] private bool directViewOnly = true;            //If you want to allow icon display even if targets aren't in direct view for the player, set it to false
    [SerializeField] private bool activateAlphaBlending = true;        //If alpha blending is needed when the icon approachs the camera viewport edges
    [SerializeField] private float alphaStartPercentage = 0.2f;     //Indicates when the icon will start going from alpha=1 to alpha=0 (0.2 = 20% of the viewport size)

    public struct TargetStruct                    //Structure that contain every icon informations
    {
        public GameObject item;                    //-the item the icon is linked to
        public Vector3 screenPos;                //-the screen position of the icon (!= world position)
        public float xSize, ySize;                //-the current size of the icon on the screen
        public float xPos, yPos;                //-the current coordinates of the screen position
        public float xTargetSize, yTargetSize;    //-the coordinates you want the icon to reach
        public float xTargetPos, yTargetPos;    //-the size you want the icon to reach on the screen
        public float distance;                    //-the distance between player and the item linked to the icon
        public bool directView;                    //-tells you if the item is in direct view or not
        public float alpha;                        //-indicates the alpha level to apply to the icon texture
    }
   
    private List<TargetStruct> TargetList = new List<TargetStruct>();//Your ICONS LIST
    private GameObject[] Targets;                                    //The GameObjects considered as targets
   
    private int targetsCount;                                        //Number of targets in the scene

    private float cameraXSize;
    private float cameraYSize;
    private float cameraXPos;
    private float cameraYPos;

    private Color guiGolor = Color.white;
   
    void Awake()                                                       
    {
//Check if the tag exists in the project
#if UNITY_EDITOR
        bool checkTag = false;
        for (int i = 0; i < UnityEditorInternal.InternalEditorUtility.tags.Length; i++)
        {
            if (UnityEditorInternal.InternalEditorUtility.tags[i].Equals(tagToFollow))
                checkTag = true;
        }
        if (!checkTag)
            Debug.LogWarning(tagToFollow + " tag not found in the project.");
#endif

        guiGolor = Color.white;

        SetCameraSpecifications();

        UpdateTargets();
    }
   
    void Update()
    {       
        //UpdateTargets();
        for (int i = 0; i<targetsCount; i++)                                                        //You have to repeat it for every icons : be aware that if you have too much that could use a lot of ressoures
        {
            TargetStruct target = new TargetStruct();                                                //You have to create a temporary TargetStruct since you can't access a variable of an element in a list directly
            target = TargetList[i];                                                                    //You take the item attached to the icon

            if (target.item)
            {
                target.screenPos = camera.WorldToScreenPoint(target.item.transform.position);            //Convert world coordinates of the item into screen ones
                target.distance = Vector3.Distance(target.item.transform.position, transform.position);    //Get the distance between item and player
            }
           
            if (target.distance > maxDistanceDisplay || target.distance < minDistanceDisplay)            //If the item is too far or too close
            {
                target.xTargetSize = minTargetIconSize;                                                //you want it to disappear
                target.yTargetSize = minTargetIconSize;                                                //or at least to be in its smaller size
            }
            else
            {
                target.xTargetSize = maxTargetIconSize / (target.distance);                            //Else you get its size with the
                target.yTargetSize = maxTargetIconSize / (target.distance);                            //distance : far<=>small / close<=>big
            }
       
            if (target.distance>maxDistanceDisplay)                                                    //If the item is too far, you set its screen position : (this way it seems as if the icon was coming away from the screen to focus your target)
            {
                if (target.screenPos.x < cameraXPos + cameraXSize * 0.5f)                            //-if it's under the center of the view field
                    target.xTargetPos = cameraXPos;                                                        //to the bottom of the screen
                else                                                                                 //-else
                    target.xTargetPos = cameraXPos + cameraXSize;                                        //to the top of the screen
               
                if ((Screen.height - target.screenPos.y) < cameraYPos + cameraYSize * 0.5f)            //-if it's on the right of the view field
                    target.yTargetPos = cameraYPos;                                                        //to the right of the screen
                else                                                                                 //-else
                    target.yTargetPos = cameraYPos + cameraYSize;                                        //to the left of the screen
            }
            else                                                                                     //If the item is NOT too far, you set its screen position :
            {
                target.xTargetPos = target.screenPos.x - target.xSize * 0.5f;                        //in x-axis to the item's x-position minus half of the icon's size
                target.yTargetPos = Screen.height - target.screenPos.y - target.ySize * 0.5f;        //in y-axis to the item's y-position minus half of the icon's size
            }

            if (activateAlphaBlending)
            {
                target.alpha = 1f;

                if (target.xPos < cameraXPos + cameraXSize * alphaStartPercentage)
                    target.alpha = Mathf.Clamp((target.xPos - cameraXPos) / (cameraXSize * alphaStartPercentage), 0f, 1f);
                else if (target.xPos + target.xSize > cameraXPos + cameraXSize * (1f - alphaStartPercentage))
                    target.alpha = 1f - Mathf.Clamp((target.xPos + target.xSize - (cameraXPos + cameraXSize * (1f - alphaStartPercentage))) / (cameraXSize * alphaStartPercentage), 0f, 1f);

                if (target.alpha == 1f)
                {
                if (target.yPos < cameraYPos + cameraYSize * alphaStartPercentage)
                    target.alpha = Mathf.Clamp((target.yPos - cameraYPos) / (cameraYSize * alphaStartPercentage), 0f, 1f);
                else if (target.yPos + target.ySize > cameraYPos + cameraYSize * (1f - alphaStartPercentage))
                    target.alpha = 1f - Mathf.Clamp(((target.yPos + target.ySize) - (cameraYPos + cameraYSize * (1f - alphaStartPercentage))) / (cameraYSize * alphaStartPercentage), 0f, 1f);
                }
                else
                {
                    if (target.yPos < cameraYPos + cameraYSize * alphaStartPercentage)
                        target.alpha -= 1f - Mathf.Clamp((target.yPos - cameraYPos) / (cameraYSize * alphaStartPercentage), 0f, 1f);
                    else if (target.yPos + target.ySize > cameraYPos + cameraYSize * (1f - alphaStartPercentage))
                        target.alpha -= Mathf.Clamp(((target.yPos + target.ySize) - (cameraYPos + cameraYSize * (1f - alphaStartPercentage))) / (cameraYSize * alphaStartPercentage), 0f, 1f);
                }
            }
           
            target.xSize = Mathf.Lerp(target.xSize, target.xTargetSize, smoothGrowingParameter*Time.deltaTime);    //You do lerps on your icons size so you can adjust
            target.ySize = Mathf.Lerp(target.xSize, target.yTargetSize, smoothGrowingParameter*Time.deltaTime);    //the speed of their resizing
           
            target.xPos = Mathf.Lerp(target.xPos, target.xTargetPos, smoothMovingParameter*Time.deltaTime);        //You do lerps on your icons position so you can adjust
            target.yPos = Mathf.Lerp(target.yPos, target.yTargetPos, smoothMovingParameter*Time.deltaTime);        //their moving speed

            if (target.item)
            {
                RaycastHit hitInfos = new RaycastHit();                                                                    //You create a new variable to stock the information of the coming raycast
                Physics.Raycast(transform.position, target.item.transform.position-transform.position, out hitInfos);    //and you RayCast from the player's position to the item's position
               
                if(hitInfos.collider.gameObject.layer==8)                                                                //HERE IS A BIT TRICKY : you have to creat new layers (I called them "Interactive Items" and "Obstacles") and to apply them to your various items.
                    target.directView=true;                                                                                //Then you select EVERY items in your scene and set their layer to "Ignore Raycast". After that you select your interactive items biggest shape (if you have big trigger colliders on them select the item that hold it),
                else                                                                                                     //and set their layers to "Interactive Items". Last part is setting every potential obstacle item layer to "Obstacles".
                    target.directView=false;                                                                            //NOTE : Here my "Interactive Items" layer number is 8
               
                TargetList[i] = target;                                                                    //You apply all the variables to your index-i icon in the ICONS LIST
            }
        }
    }
   
    void OnGUI()
    {
        GUI.color = guiGolor;
        for (int i = 0; i<targetsCount; i++)                                                                                        //For every icon
        {
            if (TargetList[i].screenPos.z>0 && (!directViewOnly || (directViewOnly && TargetList[i].directView)))                    //If the icon is in front of you and all the required conditions are okay
            {
                if (activateAlphaBlending)
                {
                    guiGolor.a = TargetList[i].alpha;
                    GUI.color = guiGolor;
                }
                GUI.DrawTexture(new Rect(TargetList[i].xPos, TargetList[i].yPos, TargetList[i].xSize, TargetList[i].ySize), targetIcon);//you display the icon with it's size and position
            }
        }
    }

    private void SetCameraSpecifications()
    {
        Rect cameraViewport =  this.camera.rect;
        cameraXPos = cameraViewport.x * Screen.width;
        cameraYPos = (1f - cameraViewport.y - cameraViewport.height) * Screen.height;
        cameraXSize = cameraViewport.width * Screen.width;
        cameraYSize = cameraViewport.height * Screen.height;
    }

    public void UpdateTargets()
    {
        Targets = GameObject.FindGameObjectsWithTag(tagToFollow);            //Get all the potential targets in the scene (just replace it by your own tag : "MyTag")
       
        foreach (GameObject target in Targets)                                    //Put every detected GameObject into your ICONS LIST
        {
            TargetStruct newTarget = new TargetStruct();
            newTarget.item = target;                                            //and attach each icon its GameObject
            newTarget.alpha = 1f;
            TargetList.Add(newTarget);
        }
       
        targetsCount = TargetList.Count;                                        //Count the number of target in the scene
    }

    public void DeleteTarget(GameObject obj, bool resetIconsPositions = false)        // 'obj' is the item tagged followed by the script
    {                                                                                // 'resetIconsPositions' allow to reset the icons positions as if the script was just being started
        for (int i = 0; i<targetsCount; i++)
        {
            TargetStruct target = new TargetStruct();
            target = TargetList[i];
            if (target.item.Equals(obj))
            {
                TargetList.RemoveAt(i);
                obj.tag = "Untagged";
                targetsCount --;
                break;
            }
        }

        if (resetIconsPositions)
            UpdateTargets();
    }
}

The DeleteTarget method can be called this way :

if (Input.GetKeyUp(KeyCode.A))
        {
            GameObject.FindGameObjectWithTag("MainCamera").GetComponent<GUIRadarTest>().DeleteTarget(this.gameObject, false);
            GameObject.FindGameObjectWithTag("Camera2").GetComponent<GUIRadarTest>().DeleteTarget(this.gameObject, false);
            Destroy(this.transform.parent.gameObject);
        }

Note that if you have many cameras being able to “target” the object (each camera having its own script), you’ll need to call the method for each of them.

Here the download link of the updated test scene : WeTransfer - Send Large Files & Share Photos Online - Up to 2GB Free

Well enjoy it !

Thanks for this! I had to start over with my project as I wanted multiplayer rather than mess about with AI and haven’t got my scanners anymore yet, so haven’t tried your changes.
I did notice though, that this doesn’t pick up multiplayer clients. Any thoughts on why that would be? The tags and layers are set up right still and things in the scene hierarchy get targeted still.

I couldn’t find this thread again at first and so googled…google came up with the script in a much larger form with a lot of the original stuff commented out…is that the latest work you’ve done on it, or an older version?

Cheers,
John

Yes the script on the forum is the latest version : I also uploaded it on my personnal website so you may hav gotten on it :wink:
On the one hosted on my website there’s also a part about the first test I did but which I finally abandonned :roll_eyes:

About the network thing, I can’t figure anything : I never worked on it so I really have no idea what could cause the malfunction.

ok, no worries. I’m using this as a start point for what I want to acheive and it’s some way off yet :smile:
Eventually, I want to be able to assign buttons to target specific things…next and previous enemy, same with friendly…target nearest craft targeting me…etc. I need to figure out how to apply yours to multiplayer clients first though.
I shall plod on and see what I can learn!

Cheers

I’ve been looking into the network problem and I notice that “update targets” is only called in the “awake” function, so I presume clients are joining after the targets have been established. The only other call to update the targets is commented out. I removed the // from that line but things went weird with the display and controls.
I thought that this was now updating the targets every frame and so obviously isn’t good, so I added “if fire3” so it would only update if fire button 3 is pressed. It then didn’t draw any targets so I commented it all out again.
Now the weird stuff starts…I put 3 stationary objects in the scene and ran it in the editor as SP…3 targets as expected. When I ran it in the editor as MP…3 targets again. However, once I build and run the project, only 1 target out of the 3 is displayed. going back to the editor in SP and MP, still only 1 target of the 3.
I duplicated the objects so there was now 5…3 targets out of 5. I then duplicated the 5 and deleted the original 5…5 targets show up…build and run…back to 3 targets of 5

I am so confused right now :smile:

Hello everyone,
Since I recently had some free time, I felt like updating this project :smile:

It now works using Unity UI and doesn’t rely anymore on old GUI: this implies far better performances and also more flexibility in scripting. This is why I decided to also improve it a bit ! :wink:

Now it features a custom editor for easy implementation and many new marker customisation (colors over distance, rotations, etc…)

You can find the updated version on the script on its GitHub repository: GitHub - Kardux/UIRadar: Unity UI Radar based on UI 4.6 (used to track targets)
If you want to try a WebGL demo of this, I uploaded one: Unity development engineer

Feel free to use it if you need it (only make sure to follow the CC-BY-SA license).

Cheers

1 Like

Hey,

I found this through google, and even though it’s outdated,I went ahead and implented it, v straightforward and did exactly what I wanted, for free as well :slight_smile:

However, I’ve run into a problem. I understand you’re not updating the code anymore, but I wanted to see if you had time to explain the DeleteTarget() method? I can’t get it to work, it just keeps returning errors…

Thanks in advance!

Hi,

Not actively working on this script but still looking for ways to improve it and help other fellow programmers :wink:

My guess is the line causing error is the a_Target.tag = "Untagged"; one. Which means the GameObject you are trying to remove from the targets list has already been destroyed: make sure to call the method before destroying the object.

If the problem is different, feel free to post a snippet of your code calling the method and the error you have so I can check what’s happening here !

Anyway I’ll probably take a look at the code and how I could update/upgrade it when coming back from vacation (1,5 week) since I didn’t touch it for Over 2 years :roll_eyes: Make sure to check it out on GitHub.

Cheers,

1 Like