c# - unity navmesh ai卡住了

标签 c# unity3d artificial-intelligence navmesh

我正在尝试在 Unity 引擎中开发一种可与光子网络系统配合使用的 AI。它应该相当简单:它跑向一个随机的玩家,直到他和玩家之间的距离达到 5 个单位,然后它以稍微慢一点的速度走到玩家的前面。然后他攻击。到目前为止一切顺利,但有时,当 AI 与玩家之间的距离达到 5 个单位时,它会卡住。我尝试了几个来自互联网的修复程序,但没有任何效果。 这是代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

[RequireComponent(typeof(NavMeshAgent))]
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(Animator))]
[RequireComponent(typeof(PhotonView))]
[RequireComponent(typeof(PhotonTransformView))]
public class EnemyAI : Photon.MonoBehaviour {

    NavMeshAgent agent;
    Animator anim;

    PlayerController target;
    [Header("Base settings")]
    [SerializeField]
    float health = 100f, damage, timeBetweenAttacks = 5f;

    [Space]
    [Header("Enemy Ragdoll")]
    [SerializeField]
    GameObject ragdoll;

    AudioSource emotAud, stepAud;

    [Space]
    [SerializeField]
    [Header("Audio")]
    List<AudioClip> attackingAuds;

    [Space]
    [Header("Sunete pasi")]
    [SerializeField]
    List<AudioClip> stepAuds;

    [Space]
    [Header("Alte optiuni")]
    [SerializeField]
    float distantaLaCareIncepeSaMearga = 5f, walkSpeed = .5f, runSpeed = 3.5f;

    bool dead, walking;

    PhotonView killer;

    float nextAttackTime;

    // Use this for initialization
    void Start () {
        emotAud = gameObject.AddComponent<AudioSource>();
        stepAud = gameObject.AddComponent<AudioSource>();

        emotAud.spatialBlend = 1;
        emotAud.maxDistance = 7;

        stepAud.spatialBlend = 1;
        stepAud.maxDistance = 7;

        emotAud.playOnAwake = false;
        stepAud.playOnAwake = false;

        dead = false;
        target = null;
        agent = GetComponent<NavMeshAgent>();
        anim = GetComponent<Animator>();
        killer = null;
    }

    // Update is called once per frame
    void Update () {
        if (photonView.isMine)
        {

            if (walking)
            {
                agent.speed = walkSpeed;
            }
            else
            {
                agent.speed = runSpeed;
            }

            if (health <= 0)
            {
                if (!dead)
                {
                    dead = true;
                    photonView.RPC("die", PhotonTargets.AllBuffered);
                }
            }

            if (!target)
            {
                if (!PhotonNetwork.offlineMode)
                {
                    nextAttackTime = (float)PhotonNetwork.room.CustomProperties["remainTime"];
                }
                else
                {
                    nextAttackTime = 0f;
                }

                PlayerController[] controllers = FindObjectsOfType<PlayerController>();
                int randCh = Random.Range(0, controllers.Length);

                if (controllers.Length > 0)
                {
                    target = controllers[randCh];
                }
                anim.SetFloat("move", 0);

            }
            else
            {

                if (Vector3.Distance(transform.position, target.gameObject.transform.position) > 1.8f)
                {
                    if (Vector3.Distance(transform.position, target.gameObject.transform.position) > distantaLaCareIncepeSaMearga)
                    {
                        walking = false;
                    }
                    else
                    {
                        walking = true;
                    }

                    anim.SetBool("walking", walking);
                    anim.SetFloat("move", 1);

                    //print("Active: " + agent.isActiveAndEnabled + " Pend: " + agent.pathPending + " Has path: " + agent.hasPath);

                    if (agent.isActiveAndEnabled)
                    {
                        if (!agent.pathPending)
                        {
                            agent.SetDestination(target.gameObject.transform.position - transform.forward * 1.2f);
                        }
                    }
                }
                else
                {
                    if (!PhotonNetwork.offlineMode)
                    {
                        if (nextAttackTime >= (float)PhotonNetwork.room.CustomProperties["remainTime"])
                        {
                            anim.SetTrigger("attack");
                            nextAttackTime -= timeBetweenAttacks;
                        }
                        else
                        {
                            anim.SetFloat("move", 0);
                        }
                    }
                    else
                    {
                        if (nextAttackTime <= 0f)
                        {
                            anim.SetTrigger("attack");
                            nextAttackTime += timeBetweenAttacks;
                        }
                        else
                        {
                            nextAttackTime -= Time.deltaTime;
                            anim.SetFloat("move", 0);
                        }
                    }
                }
            }
        }
    }

    void OnDrawGizmosSelected()
    {
        if (target)
        {
            Gizmos.color = Color.blue;
            Gizmos.DrawSphere(agent.destination, 1);
        }
    }

    [PunRPC]
    void die()
    {
        if (killer)
        {
            killer.gameObject.GetComponent<PlayerController>().kill();
        }

        if (attackingAuds.Count > 0)
        {
            emotAud.clip = attackingAuds[Random.Range(0, attackingAuds.Count - 1)];
            emotAud.Play();
        }

        gameObject.GetComponent<CapsuleCollider>().enabled = false;
        Instantiate(ragdoll, transform.position, transform.rotation);
        Destroy(this.gameObject);
    }

    public void attack()
    {
        if (target && target.health >= 0)
        {
            if (Vector3.Distance(target.gameObject.transform.position, transform.position) <= 2f)
            {
                target.doDamage(damage);
                if (target.health <= 0)
                {
                    target.photonView.RPC("die", PhotonTargets.All, true);
                }
            }
        }
    }

    void OnCollisionEnter(Collision col)
    {
        if (col.gameObject.tag.Contains("Bullet"))
        {
            killer = col.gameObject.GetComponent<Magic_Bullet>().owner;
            target = killer.gameObject.GetComponent<PlayerController>();
            photonView.RPC("takeDamage", PhotonTargets.AllBuffered, col.gameObject.GetComponent<Magic_Bullet>().damage);
            PhotonNetwork.Destroy(col.gameObject);
        }
    }

    [PunRPC]
    void takeDamage(float dmg)
    {
        health -= dmg;
    }

    public void step()
    {
        stepAud.clip = stepAuds[Random.Range(0, stepAuds.Count - 1)];
        stepAud.Play();
    }

}

我做错了什么?

最佳答案

好吧,你的更新函数中有一大堆 if else,这让我们所有人都很头疼, 相反,尝试使用 scriptableobject(如 unity 官方教程)或需要硬编码且不推荐的协程来实现简单的 FSM。

https://unity3d.com/learn/tutorials/topics/navigation/finite-state-ai-delegate-pattern

关于c# - unity navmesh ai卡住了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50439770/

相关文章:

c# - 如何使用.Net部署sqlite

c# - 对象的比较取决于其值

C# 对当前异步方法的反射(reflection)

c# - 使用构造函数初始化 POCO 实体

artificial-intelligence - 有人可以解释一下人工神经网络吗?

c# - 如何使 Sprite 颜色取决于 HP 变量? (hp 越少,红色 Sprite 应该越多)

Android - 在 Activity 中嵌入 Unity3d 场景 - 需要注销接收器吗?

c# - 从统一命名空间中的另一个类(在克隆对象上)获取一个函数,c#

java - 将速度应用于无与伦比的 AI Racket ,打造简单的乒乓球游戏

python - 使用 BERT 进行文章摘要,其中文章不存在标签或预期输出摘要