【问题标题】:Finding the closest target in a group of enemies with 3 different tags在具有 3 个不同标签的一组敌人中找到最近的目标
【发布时间】:2021-08-23 19:03:51
【问题描述】:

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

LeftPlayer 有 3 个标签,用于 3 种不同的敌人类型。 RightPlayer 有 3 个标签,用于 3 种不同的敌人类型。 所以总共有 6 个标签,每个 Player 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;
    }
}

【问题讨论】:

  • 我没有看到你在哪里检查代码中的标签...
  • 正如帖子中提到的,它在注释掉的部分。它读作敌人 = GameObject.FindGameObjectsWithTag("LeftBrute");或者你是什么意思?
  • 但是我理解错了吗,还是一个炮塔只跟随一个标签?为什么在一个脚本中需要所有三个标签?
  • 因为在任何给定时间,地图上的炮塔都可能有 3 种潜在的目标类型(标签)。我希望 TargetLocator 脚本将这 3 个标签作为一组处理,然后始终以最接近炮塔的那个为目标。由于我有两个方面,应该分别处理(LeftPlayer 和 RightPlayer),我不能使用 Udemy 的方法,它完全忽略了哪个标签属于哪个播放器,因为它没有使用任何标签。由于我找不到任何与我需要的东西相似的东西,所以我来这里寻求帮助。如果您还有任何问题,请告诉我。

标签: c# unity3d tags targeting


【解决方案1】:

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

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

【讨论】:

  • 这非常有效!非常感谢!凭借我整整 2 周的经验,我对编程有点陌生,但我从每一个错误和问题中学习,所以你真的帮助我解决了这个问题。 :) 为每种敌人类型使用单独标签的原因只是为了让货币系统知道某些敌人是否做了某些事情。我发现标签是最简单的方法,而且效果很好。可悲的是,这意味着我应该为此使用类似的方法,但与我用于货币系统的方法不同,我无法自己解决这个问题。再次感谢您!
猜你喜欢
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
  • 2017-11-20
  • 1970-01-01
  • 2022-06-23
  • 1970-01-01
  • 2021-01-22
  • 1970-01-01
相关资源
最近更新 更多