在一组具有 3 个不同标签的敌人中找到最近的目标

Finding the closest target in a group of enemies with 3 different tags

我有一个双面游戏,炮塔需要找到最近的带有特定标签的目标。

LeftPlayer 有 3 个标签,用于 3 种不同的敌人类型。 RightPlayer 有 3 个标签,用于 3 种不同的敌人类型。 所以一共6个标签,每个玩家3个。

目前我正在使用 Udemy 的 RealmRush 课程中的 FindClosestTarget 方法,该方法几乎可以正常工作,但遗憾的是双方的炮塔都瞄准所有 6 种敌人类型。这就是为什么我试图找到一个使用标签的解决方案。

我可以举出前面提到的 Udemy RealmRush 方法的例子,它可能是可以挽救的,并且可以为每一方拆分成单独的脚本,但我不知道该怎么做。该脚本还包含我注释掉的使其基于标签的失败尝试。无论我在哪里寻找解决方案,我都只找到了一个标签的示例,该标签也无法正常工作。如果您认为可以比当前版本更容易保存,我非常乐意这样做。

using Vector3 = UnityEngine.Vector3;

public class TargetLocator : MonoBehaviour
{
    [SerializeField] Transform weapon;
    [SerializeField] ParticleSystem projectileParticles;
    [SerializeField] float range = 1.5f;
    [SerializeField] Transform enemy;
    
    //public GameObject Target;
    public float maxDistance;

    void Update()
    {
        /*Target = FindClosestEnemy();

        range = Vector3.Distance(transform.position, Target.transform.position);

        if (maxDistance < range)
        {
            FindClosestEnemy();
        }*/

        FindClosestTarget();
        AimWeapon();
    }

    /*public GameObject FindClosestEnemy()
    {
        Enemy[] enemies;
        enemies = GameObject.FindGameObjectsWithTag("LeftBrute");
        GameObject closest;
        float maxDistance = Mathf.Infinity;
        Vector3 position = transform.position;
        
        foreach (Enemy enemy in enemies)
        {
            Vector3 diff = enemy.transform.position - position;
            float currentDistance = diff.sqrMagnitude;
            if (currentDistance < maxDistance)
            {
                closest = Target;
                maxDistance = currentDistance;
            }
        }

        return Target;
    }*/

    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;
            }
        }

        enemy = closestTarget;
    }

    public void AimWeapon()
    {
        float maxDistance = Vector3.Distance(transform.position, enemy.transform.position);

        if (maxDistance < range)
        {
            weapon.LookAt(enemy.transform.position);
            Attack(true);
        }
        else
        {
            Attack(false);
            Debug.Log("Target not found");
        }
    }

    public void Attack(bool isActive)
    {
        var emissionModule = projectileParticles.emission;
        emissionModule.enabled = isActive;
    }
}

不完全清楚为什么要对所有类型的敌人使用不同的标签。使用继承或接口会更好,但是,根据您的要求 - 如果您想在方法中使用三个不同标签的搜索 - 然后在其中实现三个标签的搜索。

public void FindClosestEnemy()
    {
        List<GameObject> nearestEnemies = new List<GameObject>();
        GameObject lastAddedEnemy = null;
        GameObject enemyTemp = null;

        float maxDistance = Mathf.Infinity;
        Vector3 position = transform.position;

        enemyTemp = FindNearestWithTag("LeftBrute_1"); // your tag name
        if (enemyTemp != null && enemyTemp != lastAddedEnemy)
        {
            nearestEnemies.Add(enemyTemp);
            lastAddedEnemy = enemyTemp;
        }

        enemyTemp = FindNearestWithTag("LeftBrute_2"); // your tag name
        if (enemyTemp != null && enemyTemp != lastAddedEnemy)
        {
            nearestEnemies.Add(enemyTemp);
            lastAddedEnemy = enemyTemp;
        }

        enemyTemp = FindNearestWithTag("LeftBrute_3"); // your tag name
        if (enemyTemp != null && enemyTemp != lastAddedEnemy)
        {
            nearestEnemies.Add(enemyTemp);
            lastAddedEnemy = enemyTemp;
        }

        foreach (var enemy in nearestEnemies)
        {
            Vector3 diff = enemy.transform.position - position;
            float currentDistance = diff.sqrMagnitude;
            if (currentDistance < maxDistance)
            {
                enemyTemp = enemy;
                maxDistance = currentDistance;
            }
        }

        Target = enemyTemp;
    }

    private GameObject FindNearestWithTag(string tagName)
    {
        GameObject[] enemies;
        enemies = GameObject.FindGameObjectsWithTag(tagName);
        GameObject closest = null;
        float maxDistance = Mathf.Infinity;
        Vector3 position = transform.position;

        foreach (var enemy in enemies)
        {
            Vector3 diff = enemy.transform.position - position;
            float currentDistance = diff.sqrMagnitude;
            if (currentDistance < maxDistance)
            {
                closest = enemy;
                maxDistance = currentDistance;
            }
        }

        return closest;
    }