AI Turret Targeting Help

New day, new problem…

My game features a heavy dependency on RTS-style space combat. In keeping with this, I have turrets built on my ship models. As of right now I have them looking good and firing nicely (for now) … I just need help aiming them.

My basic idea is for the turrets to somehow “sense” an enemy target, orient towards it (flat rotation of the z axis only, a la a “real world” turret), elevate or depress the guns, and fire.

I’m currently using the included SmoothLookAt.js script:

var target : Transform;
var damping = 6.0;
var smooth = true;

@script AddComponentMenu("Camera-Control/Smooth Look At")

function LateUpdate () {
	if (target) {
		if (smooth)
		{
			// Look at and dampen the rotation
			var rotation = Quaternion.LookRotation(target.position - transform.position);
			transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);
		}
		else
		{
			// Just lookat
		    transform.LookAt(target);
		}
	}
}

function Start () {
	// Make the rigid body not change rotation
   	if (rigidbody)
		rigidbody.freezeRotation = true;
}

And I’m thinking either a Raycast or LineCast to tell the gun barrel when it’s pointed towards a target (completely unfamiliar with both, so that may not work).

My biggest question is… how do I script the turret to sense and target? Especially since, given the RTS nature of the game, it won’t be the same scene every time? I knew how to do this in Blender, but scripting is just confounding me… any help will be appreciated!

check if target is null, if it is, call a function called something like AssignTarget

In that function use physics.OverlapSphere to find a new target within range.

Any chance you can expand on that a bit? Not trying to be greedy but I’m new to all this and I don’t always understand the language.

function LateUpdate()
{
  if(target)
  {
    ///do targetting stuff

  } else AssignTarget();
  

}

fucntion AssignTarget()
{
   var hitColliders = Physics.OverlapSphere(center, radius);
		
		for (var i = 0; i < hitColliders.Length; i++) {

                 //choose a target... based on distance/tags/etc

		}
}

Ok I think I get that

The only thing I’m unsure of is (what I would like to do) assigning targets based on distance (closest first, etc)

I’ve looked through pretty much everything in the Scripting Reference… still not finding any method of choosing targets… I assume there’s something major I’m missing here? It seems like it should find targets, but how do I get it to then orient on the targets?

#pragma strict

var target : Transform;
var damping = 6.0;
var smooth = true;

@script AddComponentMenu("Camera-Control/Smooth Look At")

function LateUpdate () {
    if (target) {
        if (smooth)
        {
            var rotation = Quaternion.LookRotation(target.position - transform.position);
            transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);
        }
        else
        {
            transform.LookAt(target);
        }
    } else FindClosestEnemy ()
}

function FindClosestEnemy() {
	// Find all game objects with tag Enemy
        var gos : GameObject[];
        gos = GameObject.FindGameObjectsWithTag("Enemy"); 
        var closest : GameObject; 
        var distance = Mathf.Infinity; 
        var position = transform.position; 
    // Iterate through them and find the closest one
        for (var go : GameObject in gos)  { 
            var diff = (go.transform.position - position);
            var curDistance = diff.sqrMagnitude; 
            if (curDistance < distance) { 
                closest = go; 
                distance = curDistance; 
            } 
        } 
        return closest;    
}

function Start () {
    if (rigidbody)
        rigidbody.freezeRotation = true;
}

There’s a bug in that script - you’re returning the closest enemy from FindClosestEnemy, but you’re not actually assigning it to anything. It should be assigned to target.

Also, you’re finding everything in the entire scene, which may be fine if your total number of enemies is small. If number gets significant though - or the guns are supposed to have a limited sight range - then OverlapSphere would be a better option.

Am I not…? I guess there’s something I’m not understanding then.

Yeah I tried that - waayyyyy too confusing for my limited knowledge and ability. Literally stared at it for half an hour and gave up on figuring out what any of that meant.

line 20:

else target = FindClosestEnemy();

That generates an error message:

Assets/HeavyGunTurret.js(20,38): BCE0022: Cannot convert ‘UnityEngine.GameObject’ to ‘UnityEngine.Transform’.

the error is coming because, your target is Transform and you are returning a gameObject from your FindClosestEnemy() function. try the script given below i changed your script a little bit.

#pragma strict

 

var target : Transform;

var damping = 6.0;

var smooth = true;

 

function LateUpdate () {

    if (target) {

        if (smooth)

        {

            var rotation = Quaternion.LookRotation(target.position - transform.position);

            transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * damping);

        }

        else

        {

            transform.LookAt(target);

        }

    } 
    else 
    {
    	target = FindClosestEnemy ();
    }

}

 

function FindClosestEnemy() {

    // Find all game objects with tag Enemy

        var gos : GameObject[];

        gos = GameObject.FindGameObjectsWithTag("Player"); 

        var closest : GameObject; 

        var distance = Mathf.Infinity; 

        var position = transform.position; 

    // Iterate through them and find the closest one

        for (var go : GameObject in gos)  { 

            var diff = (go.transform.position - position);

            var curDistance = diff.sqrMagnitude; 

            if (curDistance < distance) { 

                closest = go; 

                distance = curDistance; 

            } 

        } 

        return closest.transform;    

}

 

function Start () {

    if (rigidbody)

        rigidbody.freezeRotation = true;

}