Unity 中是否有 C# 函数来检测设定范围内的某种类型的游戏对象?

Is there a C# function in unity to detect a certain type of gameObject within a set range?

提问人:Kurt Roberts 提问时间:11/17/2023 更新时间:11/18/2023 访问量:49

问:

我正在编写一个生存游戏,我希望敌人在特定范围内(例如 10m)内瞄准最近的玩家。有没有检测最近的玩家的功能,以便我可以对攻击和动作进行编程?

我尝试分配玩家并使用简单的 GameObject.LookAt 进行操作,但这不允许针对多个玩家,我只希望玩家在一定范围内成为目标。

C# unity-游戏引擎

评论

0赞 BugFinder 11/17/2023
好吧,你可以做一个球体广播,看看一个区域内是否有玩家,或者通过所有玩家为每个玩家选择最近的玩家。
0赞 Kurt Roberts 11/17/2023
我对所有这些编程内容都很陌生,这仅仅是“gameObject.sphercast(10.0f)”吗?对不起,如果这是一个愚蠢的问题,我只是难以找到答案
0赞 BugFinder 11/17/2023
不,这是一个物理问题 - eUnity 文档非常有帮助
1赞 Max Play 11/17/2023
另外,我认为这个问题不适合 StackOverflow。你可能需要一个导师或一群人来帮助解决这些问题,因为这个问题的正确答案是:不,Unity没有这个功能,你必须自己制作。
1赞 BugFinder 11/17/2023
Spherecast vs Itteration 也取决于有多少敌人,但这是需要分析和决定的事情

答:

0赞 Priyansh Yadav 11/18/2023 #1

这很容易。您也可以按照 @BugFinder 的评论中的建议使用球体投射来实现它。但是,我建议使用简单的 GameObject.Find 方法。

首先,您应该制作一个玩家单行为并将其附加到所有玩家。

public class PlayerMono : MonoBehaviour
{
    // Implement you player code here
}

然后,在敌人的单一行为中 - 要找到最近的玩家,请添加以下代码。

public class EnemyMono : MonoBehaviour
{
    // Your custom code here...

    private PlayerMono[] allPlayers; // This list should be cached bcz it has a little bit of overhead which makes it non-feasible to be called everytime.

    private PlayerMono GetNearestPlayer(Vector3 enemyPosition)
    {
        if (allPlayers  == null)
        {
            allPlayers = GameObject.FindObjectsOfType<PlayerMono>();
            // otherwise do the following if you dont have a PlayerComponent and change PlayerMono references with GameObject
            // allPlayers = GameObject.FindGameObjectWithTag("PlayerTag");
        }

        // Make sure to not cache the following array as it will not take into account the updated positions of the Player.
        Vector3[] allPlayersPositions = allPlayers.Select(player => player.transform.position).ToArray();

        PlayerMono nearestPlayer = allPlayers[GetNearestPlayerIndex(transform.position, allPlayersPositions)];
        return nearestPlayer;
    }

    // You need to install the Burst Package for this. If it confuses you,
    // simply comment the [BurstCompile]. It won't have any effect on the result of the code.
    // I just tend to do this as a habit for such functions where i am looping over vectors or other such types.
    [BurstCompile]
    private int GetNearestPlayerIndex(Vector3 enemyPosition, Vector3[] allPlayersPositions)
    {
        Vector3 nearestPosition = Vector3.positiveInfinity;
        int nearestPlayerIndex = 0;

        int currentIndex = 0;

        foreach (var playerPosition in allPlayersPositions)
        {
            if (Vector3.Distance(enemyPosition, playerPosition) < nearestPosition.magnitude)
            {
                nearestPosition = playerPosition;
                nearestPlayerIndex = currentIndex;
            }

            currentIndex++;
        }

        return nearestPlayerIndex;
    }
}

现在你可以对最近的玩家做任何你想做的事情,比如:

PlayerMono nearestPlayer = GetNearestPlayer();
if (Vector3.Distance(transform.position, nearestPlayer.transform.position) <= 10f)
{
    AttackPlayer(nearestPlayer); // implement it according to your needs.
}
else
{
    JustRelax(); // Exhibit Idle behaviour
}

评论

0赞 derHugo 11/19/2023
如果已经在使用 Linq,您可以继续使用FindObjectsOfType<PlayerMono>().OrderBy(o => (transform.position - o.tranaform.position).sqrMagnitude).FirstOrDefault();