Turret Not Targeting Right

//My turrets were shooting their targets just fine until I added the SetTarget(); method. I’m not sure what could be going on. Also let me know if there is a better way to upload code to a topic.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Turret : MonoBehaviour
{
public Transform Target;
public Transform RotatingObject;
[SerializeField] private float attackRange = 10;
[SerializeField] private ParticleSystem bulletParticles;
void Start()
{

}

// Update is called once per frame
void Update()
{
    SetTarget();
    if (Target)
    {
        RotatingObject.LookAt(Target);
        ShootEnemy();
    }
    else
    {
        Shoot(false);
    }
   
}

private void SetTarget()
{
    var sceneEnemies = FindObjectsOfType<DamageToEnemy>();
    if(sceneEnemies.Length == 0) { return; }
    Transform closestEmemy = sceneEnemies[0].transform;
    foreach(DamageToEnemy testEnemy in sceneEnemies)
    {
        closestEmemy = GetCloesest(closestEmemy, testEnemy.transform);
    }
    Target = closestEmemy;
}

private Transform GetCloesest(Transform transformA, Transform transformB)
{
    var aDistance = Vector3.Distance(transform.position, transformA.position);
    var bDistance = Vector3.Distance(transform.position, transformB.position);
    if(aDistance < bDistance)
    {
        return transformA; 
    }
    return transformB;
    
}

private void ShootEnemy()
{
    float distanceToEnemy = Vector3.Distance(Target.transform.position, gameObject.transform.position);
    if (distanceToEnemy < attackRange)
    {
        Shoot(true);
    }
    else
    {
        Shoot(false);

    }

}

private void Shoot(bool isActive)
{
    var emit = bulletParticles.emission;
    emit.enabled = isActive;
}

}

I’m not sure what the problem is. Are your turrets not shooting anything? Do the enemies have DamageToEnemy components? Only thing I can see that would cause the turrets to not shoot at enemies is if it can’t find any enemies

There is a little issue (which wouldn’t explain your problem)

if(sceneEnemies.Length == 0) { return; }

If you previously had a Target set and there are no more enemies left, this will just return and all the turrets will still try to shoot an enemy that no longer exists. Instead of just returning here, also set Target = null

This is close, but you’d want to wrap the code in ` (backticks, not single quotes). Three of them for blocks of code. See this post: How to apply code formatting within your post

The turrets are shooting the targets correctly but when I add the new method then they start shooting right below the target, missing it completely.

The turrets shoot at the game object that holds the DamageToEnemy component. If this object is at the base of the enemy, the turrets will shoot at the base of the enemy. Can you show an enemy and where exactly the DamageToEnemy script is located?

This looks great, btw

Thank you! :slight_smile: Here are the locations


The parent object (enemies - holds all enemies) holds a child (enemy - holds scripts and box collider) which holds another child (body - holds the mesh renderer and mesh filter). I have the scripts placed on (enemy) as shown in the lesson.

And for some reason, when using the move tool, the arrows for moving the object are positioned above the object, not on it. Similarly, the distance of how far off the turrets aim is and the distance of how far the arrows are above the game object are the same distance. Is there a way to fix this without moving the child object? I think that may help.

The turrets are going to aim at those arrows. But, that’s the game object’s origin. You can’t move it without moving the game object.
What I would do is to

  • add an empty child game object to the Enemy and call it something like ‘Target Position’, so the hierarchy would be
Enemy
  ├ Body
  └ Target Position

NOTE You could use the ‘Body’ object instead of adding a new empty game object. This would then mean you can’t move it around 'cos you’ll move the mesh, but it should be the middle of the enemy

Then, either

  • Create a TargetMarker.cs script and add it to this empty game object. It’s an empty script (remove the boilerplate code) that really just serves as a way to find it.
  • In the Turret script, replace the FindObjectsOfType<DamageToEnemy> with FindObjectsOfType<TargetMarker>.

Or

  • Add a field to the DamageToEnemy script called _targetPosition and a ‘getter’ method
[SerializeField] Transform _targetPosition;

public Vector3 GetTargetPosition()
{
    return _targetPosition.position;
}
  • Drag the ‘Target Position’ object into this field in the inspector
  • In the Turret script, ‘get’ this position and use that instead of the DamageToEnemy script’s position, so you’ll still use FindObjectsOfType<DamageToEnemy> but then you’ll use the getter (and obviously change the code a little because this will give you the Vector3 position instead of a transform)
closestEmemy = GetCloesest(closestEmemy, testEnemy.GetTargetPosition());

For both options (if you didn’t opt for using the ‘Body’ instead)

  • Position this empty game object where you want the turrets to aim

Lastly, I’d fix all the typos (because they’ll drive me insane) :stuck_out_tongue_winking_eye:

Privacy & Terms