I wanted to make a missile locking/Targeting system, Like you would find in the Arma series. When targeted a icon appears on the GUI, Locking is based on range and if there is nothing blocking view, such as terrain.

 

The GUI icon is pretty simple:

1

This is created with a quite simple piece of code

    public Texture2D targetTexture;
    public Transform target;

    private Vector3 guiPos;

    void Update () {
        guiPos = cam.WorldToScreenPoint(target.position);    
        guiPos.x = guiPos.x - 12.5f;
        guiPos.y = Screen.height - (guiPos.y - 20f);        
    }

    void OnGUI(){
        if (target.transform.renderer.isVisible){
            GUI.DrawTexture(new Rect(guiPos.x,guiPos.y,50f,50f),targetTexture);
        }
    }

“if (target.transform.renderer.isVisible)” Is on here because “cam.WorldToScreenPoint” shows the same coordinates on the reverse of the camera, So if you look behind it would show up there.

 

The main script is pretty simple to start off, To find all targetable objects all I did was Create a new Unity Tag called “targets” and applied it to the game objects in the editor. Then in the script i create a List and use Unitys built in “FindGameObjectsWithTag” to add them all into the list. Now i cant keep that list because a target might be destroyed or go out of range so I i had to go through each list item every time the target key was pressed checking these statuses removing or added them and ended up with this:

 

if(Input.GetKeyDown(KeyCode.Tab)){

        targets.Clear();
	targetList.Clear();

	targets.AddRange(GameObject.FindGameObjectsWithTag("Targets"));

	for(int i = 0; i < targets.Count; i++){
		if(Vector3.Distance(heli.position,targets[i].transform.position) < targetRange){
			if(!targetList.Contains(targets[i])){
				targetList.Add(targets[i]);
				Debug.Log("added");
			}
			Debug.Log("Already exists");
		} else {
			if(targetList.Contains(targets[i])){
				targetList.Remove(targets[i]);
				Debug.Log("removed");
			}
			Debug.Log("Not in list");
		}
	}

I also added a function to unset a target if they went out of range. Next problem was that, On Arma you also have a name displayed of the target such as T-72 on a per-target basis. To sort this out i created a new script that would be applied to all targets stating the name, But this also allowed me to include a vehicle type such as “air, water, ground”, for weapons such as a AIM-9 Sidewinder missile as these are only Air-Air missiles so cannot be targeted at ground or water targets. This is just a few lined script:

using UnityEngine;
using System.Collections;

public class targetDetails : MonoBehaviour {
	public string name;
	public bool ground;
	public bool air;
	public bool water;
}

To get these details in the script and also set a target in a orderly like fashion, So you don’t end up targeting the same one most times, was created like so:

if(targetInt >= targetList.Count) { targetInt = 0; }

if(targetList.Count == 0){ 
	target = null;
} else{
	target = targetList[targetInt].transform;
	details = target.GetComponent<targetDetails>();
	targetInt++;
}

All i needed to do next was allow a way for the missiles to get the target at any time, This is simple by a Public Get method:

public Transform GetTarget(){
    return target;
}

With all this in place the script was working great, Minus the terrain blocking and type checking. which I plan on adding later when I include new types of missiles and this post will be updated then.


Leave a Reply

Your email address will not be published.