如何在 Unity 中冻结敌人的 Ai 位置?

How Can I Freeze Enemy Ai Position In Unity?

我正在 Unity 中制作 FPS 游戏,我的玩家的一项能力是 'freeze' 任何敌人。目前我已经尝试了 3 种方法:

我用waypoints让我的敌人在地图上巡逻。

敌人移动代码:

public class EnemyControls : MonoBehaviour
{
    NavMeshAgent agent;

    private Rigidbody rb;
    [SerializeField] Animator animator;

    bool isPatroling;

    public GameObject waypoints;

    int waypointIndex;
    Vector3 target;

    float xWanderRange;
    float zWanderRange;

    private float freezeDur = 1.5f;

    void Awake()
    {
        agent = GetComponent<NavMeshAgent>();
        animator = GetComponent<Animator>();
    }

    void Start()
    {
        animator.SetBool("isPatroling", true);

        waypointIndex = 0;
        UpdateDestination();
    }

    void Update()
    {
        // checking if ai has reached destination or last waypoint.
        if (waypointIndex == waypoints.transform.childCount - 1 && agent.remainingDistance < 0.5f)
        {
            xWanderRange = Random.Range(-10.0f, 10.0f);
            zWanderRange = Random.Range(-10.0f, 10.0f);

            // checks that the distance is big enough to move enemy.
            if ((xWanderRange < -5.0f || xWanderRange > 5.0f) && (zWanderRange < -5.0f || zWanderRange > 5.0f))
            {
                Vector3 targetPosition = new Vector3(xWanderRange, 0, zWanderRange) + transform.position;

                NavMeshHit hit;
                if (NavMesh.SamplePosition(targetPosition, out hit, 1.0f, NavMesh.AllAreas))
                {
                    agent.destination = hit.position;
                }
            }
        }

        else if (agent.remainingDistance < 1.0f)
        {
           // Debug.Log("Reached destination");
            IterateWaypointIndex();
            UpdateDestination();
        }
    }

    void UpdateDestination()
    {
        target = waypoints.transform.GetChild(waypointIndex).position;
        agent.SetDestination(target);
    }

    void IterateWaypointIndex()
    {
        waypointIndex++;
        if (waypointIndex == waypoints.transform.childCount)
        {
            waypointIndex = 0;
        }
    }

    public void StopEnemy()
    {
        // make enemy destination their position.
        // agent.destination = transform.position;

        Debug.Log("freeze enemy");
        agent.ResetPath();

        animator.SetBool("isPatroling", false);

       // Invoke("UpdateDestination", freezeDur);
    }
}

你试过的方法哪里出了问题?我会在那里放一个 isFrozen 位,然后在 Update 步骤上保释,例如:

public class EnemyControls : MonoBehaviour
{
    private bool isFrozen = false;
    // stuff
    void Update()
    {
        if(isFrozen)
        {
            return;
        }
        // more Update stuff
    }

    // more stuff

    public void StopEnemy()
    {
        // make enemy destination their position.
        // agent.destination = transform.position;
        
        Debug.Log("freeze enemy");
        isFrozen = true;
       
        animator.SetBool("isPatroling", false);
        
        // Invoke("UpdateDestination", freezeDur);
    }
float timer = 0;
bool isFrozen = false;
void Update()
    {
    if(isFrozen){
        timer+= Time.deltaTime; //If isFrozen is true, ten add time to our timer

        if(timer > freezeDur){ // If the timer reaches freezeDur then unfreeze and reset the timer.
            isFrozen = false;
            timer = 0;

        }
    return; //finally return statement so you will not execute code below this loop so the agent wont be able to move untill he is unfrozen.
    }

        // checking if ai has reached destination or last waypoint.
        if (waypointIndex == waypoints.transform.childCount - 1 && agent.remainingDistance < 0.5f)
        {
            xWanderRange = Random.Range(-10.0f, 10.0f);
            zWanderRange = Random.Range(-10.0f, 10.0f);

            // checks that the distance is big enough to move enemy.
            if ((xWanderRange < -5.0f || xWanderRange > 5.0f) && (zWanderRange < -5.0f || zWanderRange > 5.0f))
            {
                Vector3 targetPosition = new Vector3(xWanderRange, 0, zWanderRange) + transform.position;

                NavMeshHit hit;
                if (NavMesh.SamplePosition(targetPosition, out hit, 1.0f, NavMesh.AllAreas))
                {
                    agent.destination = hit.position;
                }
            }
        }

        else if (agent.remainingDistance < 1.0f)
        {
           // Debug.Log("Reached destination");
            IterateWaypointIndex();
            UpdateDestination();
        }
    }

public void StopEnemy()
{
    // make enemy destination their position.
    // agent.destination = transform.position;

    Debug.Log("freeze enemy");
    //agent.ResetPath();

    animator.SetBool("isPatroling", false);
agent.destination = transform.position; //Set the destination to its current position to stop the NPC
isFrozen = true; //Set this to true to check in update (Needs refactoring dont use Update too much. Try coroutines?
   // Invoke("UpdateDestination", freezeDur);
}

请参阅上面的 //Comments 以了解我的更改说明。祝你好运!