Here is advanced version of blinking marker script that you see in my video above:
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
public class BlinkingMarker : MonoBehaviour
{
[Header("Marker Settings")]
[Tooltip("Tags of objects to track")]
public string[] tagsToMark;
[Tooltip("UI prefab for the marker")]
public GameObject spriteObject;
[Tooltip("Parent transform for all markers")]
public RectTransform markersParent;
private Dictionary<GameObject, GameObject> trackedObjects = new Dictionary<GameObject, GameObject>();
private Camera mainCamera => Camera.main; // Store the main camera reference
void Start()
{
// Find the main camera on start. You might need to adjust this if your camera setup is more complex.
//mainCamera = Camera.main;
if (mainCamera == null)
{
Debug.LogError("Main Camera not found! Make sure you have a Camera tagged as MainCamera in your scene.");
}
}
void Update()
{
// Check for new objects and update existing markers every frame.
// This is necessary because objects can be spawned and destroyed dynamically.
UpdateTrackedObjects();
UpdateMarkerPositions();
}
void UpdateTrackedObjects()
{
// Find all objects with the specified tags
foreach (string tag in tagsToMark)
{
GameObject[] foundObjects = GameObject.FindGameObjectsWithTag(tag);
foreach (GameObject obj in foundObjects)
{
// If the object is not already being tracked, create a marker for it
if (!trackedObjects.ContainsKey(obj))
{
CreateMarker(obj);
}
}
}
// Check for destroyed objects and remove their markers
List<GameObject> objectsToRemove = new List<GameObject>();
foreach (var pair in trackedObjects)
{
if (pair.Key == null) // Object has been destroyed
{
objectsToRemove.Add(pair.Key);
Destroy(pair.Value); // Destroy the marker
}
}
foreach (GameObject obj in objectsToRemove)
{
trackedObjects.Remove(obj);
}
}
void CreateMarker(GameObject targetObject)
{
if (spriteObject == null || markersParent == null)
{
Debug.LogError("Sprite Object or Markers Parent is not assigned!");
return;
}
if (mainCamera == null)
{
Debug.LogError("Main Camera not found! Make sure you have a Camera tagged as MainCamera in your scene.");
return;
}
GameObject marker = Instantiate(spriteObject, markersParent);
marker.SetActive(true); // Ensure the marker is active
trackedObjects.Add(targetObject, marker);
}
void UpdateMarkerPositions()
{
if (mainCamera == null)
{
Debug.LogError("Main Camera not found! Make sure you have a Camera tagged as MainCamera in your scene.");
return;
}
foreach (var pair in trackedObjects)
{
GameObject targetObject = pair.Key;
GameObject marker = pair.Value;
if (targetObject != null && marker != null)
{
// 1. Convert world position to screen position
Vector3 screenPosition = mainCamera.WorldToScreenPoint(targetObject.transform.position);
// 2. Check if the object is in front of the camera
if (screenPosition.z > 0)
{
// 3. Convert screen position to canvas local position
Vector2 anchoredPosition;
// For Screen Space - Overlay canvas, pass null as camera
RectTransformUtility.ScreenPointToLocalPointInRectangle(
markersParent,
screenPosition,
null, // Or mainCamera if your canvas is in Screen Space - Camera
out anchoredPosition
);
// 4. Set marker position
marker.GetComponent<RectTransform>().anchoredPosition = anchoredPosition;
marker.SetActive(true);
}
else
{
marker.SetActive(false);
}
}
}
}
}
To make the marker object interesting, add some animation to it, for example blinking, fading, etc.
I have old version of this script in this post: https://thirteenov.ciihuy.com/blinking-marker-unity-screen-space-marker-overlay-script/