Locking in a single target while in range?

I’m up to the rebalancing lecture in the course, and one thing I really want to achieve before going forward involves changing how the target locator works. Currently, the towers will constantly seek for the closest target, switching targets other targets get closer, even if their initial target is still within their firing range. My goal is to make each tower stick to one target until it goes out of range. I was trying to see if I understood enough about coding in C# to change this myself, but I can’t get it to work and was hoping for some pointers.

I added a new bool called “targetAcquired” which is initialised as “false” and added code to the bottom of the FindClosestTarget method:

I then changed Update so that FindClosestTarget is only performed if the target has not been acquired.
image

When I run the game, the tower targets the first enemy correctly, and doesn’t select a new target even when others are closer. However, it does not select a new target even when the initial target is out of range. It just looks at it as it moves around the map, and if it is destroyed and respawned, it follows it from the start again.

Can someone tell me where I’m going wrong?

I had some drinks, so i might be wrong about the last part but its not working because;

Once “targetAquired” is true, it can never be false again,
since your code to do so is inside “FindClosestTarget”

I guess if you make it a separate method and in update put like

    void Update()
    {
        if(targetAquired == false)
        { FindClosestTarget(); }
        else
        { NewMethodHere(); }

        AimWeapon();
    }

it should work?

Also in the future link your code as text, not a screenshot, it makes it easier for people to help you :wink:

you can paste code between 3 grave symbols <```> above and below it

Thanks for the advice, and sorry for the code format.
I edited my code as follows:

void Update()
    {
        if(targetAcquired == false)
        {FindClosestTarget();}
        else
        {
            KeepCurrentTarget();
        }
        AimWeapon();
    }
void FindClosestTarget()
    {
        Enemy[] enemies = FindObjectsOfType<Enemy>();
        Transform closestTarget = null;
        float maxDistance = Mathf.Infinity;
                
        foreach(Enemy enemy in enemies)
        {
            float targetDistance = Vector3.Distance(transform.position, enemy.transform.position);
            if(targetDistance < maxDistance)
            {
                closestTarget = enemy.transform;
                maxDistance = targetDistance;
            }
        }
        target = closestTarget;
        targetAcquired = true;
       } 

void KeepCurrentTarget()
        {
        float closestTargetDistance = Vector3.Distance(transform.position, target.transform.position);
        if(closestTargetDistance  <= range)
        {
            targetAcquired = true;
        }
        else
        {
            targetAcquired = false;
        } 
        }

The towers now behave more or less as I want them to, which had the side-effect of making the game a bit harder, but at least more in line of what I wanted. One issue is that if a tower destroys a target and there are no other enemies in range, it will continue to fire at the spot the enemy was in until something comes into range. I guess that’s because the AimWeapon method is holding onto the last known enemy’s position, which is technically still in range. It doesn’t have a massive impact on the game but maybe I can think of a way around it.

I resolved the above issue with firing at empty spaces this way:

    {
        float targetDistance = Vector3.Distance(transform.position, target.position);
        weapon.LookAt(target);
        
        if(targetDistance <= range && target.gameObject.activeInHierarchy == true) 
        {Attack(true);}
        else
        {Attack(false);}
    }

However, I noticed that after a time, the towers would seemingly randomly take a very long time to find a new target (they will, for a few seconds after destroying a target, keep aiming at the space it was in, and not find a new target).

I therefore made this change to the KeepCurrentTarget method, and now the towers will immediately find a new target after one goes out of range or one is destroyed:

        {
        float closestTargetDistance = Vector3.Distance(transform.position, target.transform.position);
        if(closestTargetDistance  <= range && target.gameObject.activeInHierarchy == true)
        {
            targetAcquired = true;
        }
        else
        {
            targetAcquired = false;
        } 
        }

Basically I made it so it will start looking for a new target if the previous target is no longer active. Previously it would stick to its past target even if it was destroyed, until something came along that was closer.

I think the simple solution would be to just check if the current target is still in range and then not select a new target if it is. Add a small method that checks if the target is still in range and if it’s not, Find a new one

private bool TargetInRange()
{
    // If target is null, we have no target in range
    if (target == null) return false;
    var targetDistance Vector3.Distance(transform.position, target.position);
    return targetDistance <= range;
}

Then in Update()

// If the target is not in range, pick a new one
if (!TargetInRange()) FindClosestTarget();
AimWeapon();

Edit
I see now that the targets are not destroyed but set inactive. So, once a target is no longer in range, just set it to null. This will force a new search

private bool TargetInRange()
{
    // If target is null, we have no target in range
    if (target == null) return false;
    var targetDistance Vector3.Distance(transform.position, target.position);
    // check if we should clear our target
    var inRange = targetDistance <= range;
    if (!inRange) target = null;
    return inRange;
}

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms