Unity 2D Target Scanner

Target scanners are essential for any game where you have an enemy mob that actively looks for prey. One way to scan for targets is to cast a circular physics ray based on the radius area you would like to scan.

Below is a quick and helpful intro I’ve put together for anyone who needs a quick and easy target scanner to notify another script via event subscription. It searches for targets based on the tags set through the Unity Inspector.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Simple2DTargetScanner : MonoBehaviour
{
public float scanFrequency; //in seconds
public float scanRadius = 5; //in world units
private float scanFrequencyCounter = 0; //counter for time between scans
public string[] targetTagArray; //array of tags of GameObjects to include
//delegate event to notify subscribed scripts
public delegate void TargetHit(Transform target);
public event TargetHit OnTargetHit;
public Color editorCircleColor = Color.green; //circle colour for editor
public bool scannerEnabled = true; //enable or disable scanner (or you can just enable/disable script if you prefer)
// Update is called once per frame
void FixedUpdate()
{
//if not enabled, return to stop code below from running.
if (!scannerEnabled)
return;
//counter to track time between scans
scanFrequencyCounter += Time.deltaTime;
//once counter reaches the total time we set between scans, we scan for target and reset counter to zero.
if (scanFrequencyCounter >= scanFrequency)
{
scanFrequencyCounter = 0;
//using Physics2D we will draw a circle and use a 2d raycast to see what objects are within it.
//Targets must have collider for raycast to return or it won't be detected with this method.
RaycastHit2D[] raycastHit2D = Physics2D.CircleCastAll(this.transform.position, scanRadius, Vector2.right, scanRadius * 2f);
//if we hit any targets, notify listeners that need this info
//make sure to check if OnTargetHit is null or not in case no subscribers (but if no subscribers, why using this at all? 😉 )
if (raycastHit2D.Length > 0 && OnTargetHit != null)
{
for(int i = 0; i < raycastHit2D.Length; i++)
{
//Important note: if you have a lot of target scanners running at once, for performance it might be better to just scan based on
//layers rather than compare gameobject tags.
for (int t = 0; t < targetTagArray.Length; t++)
{
if (raycastHit2D[i].transform.CompareTag(targetTagArray[t]))
{
//delgate event
OnTargetHit(raycastHit2D[i].transform);
//break out of both loops after first hit
i = raycastHit2D.Length + 1;
break;
}
}
}
}
}
}
//Unity editor code. Make sure to use hashtag UNITY_EDITOR so this code doesn't compile to non-editor build.
#if UNITY_EDITOR
//Draw gizmo wire disc (circle) when GameObject is selected.
//If you want it to always draw, then you can use void OnDrawGizmos() instead
void OnDrawGizmosSelected()
{
//set gizmo colour.
UnityEditor.Handles.color = editorCircleColor;
//draw wire circle (disc in unity lingo) based on radius variable you set.
UnityEditor.Handles.DrawWireDisc(this.transform.position, this.transform.forward, scanRadius);
}
#endif
}

How to use from another script:

//Method activated when Simple2DTargetScanner OnTargetHit event is called.
void OnTargetHit(Transform target)
{
//do something with target hit
}
void OnEnable()
{
//subscribe to Simple2DTargetScanner OnTargetHit event notification if GameObject is enabled.
this.transform.GetComponent<Simple2DTargetScanner>().OnTargetHit += OnTargetHit;
}
void OnDisable()
{
//unsubscribe to Simple2DTargetScanner OnTargetHit event notification if GameObject is disabled
this.transform.GetComponent<Simple2DTargetScanner>().OnTargetHit -= OnTargetHit;
}
view raw EnemyMob.cs hosted with ❤ by GitHub

 

Final notes:

This is a simple solution if you only require a few dozen scanners running at a time or less. If you have many more running concurrently then using tags may be slower and I would recommend scanning based on Unity Layers. You can set which layer to RayCast2D on or alternatively, you can set in Project Settings -> Physics 2D and set which physics layers interact with one another.

Leave a Reply

Your email address will not be published. Required fields are marked *