我正在尝试在统一引擎中开发一个与光子网络系统配合使用的AI。它应该是相当简单的:它运行到一个随机玩家,直到它与玩家之间达到5个单位的距离,然后它以稍慢的速度行走直到它到达玩家的前方。然后他攻击。到目前为止一直很好,但有时候,当他和玩家之间的距离达到5个单位时,AI就会卡住。我尝试了几个来自互联网的修复程序,但没有任何效果。 这是代码:
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();
}
}
我做错了什么?
答案 0 :(得分:3)
那么你的更新功能还有什么地方让我们所有人都头疼, 相反,尝试使用scriptableobject(作为统一官方教程)或Coroutines实现一个简单的FSM,它需要硬编码,不建议使用。
https://unity3d.com/learn/tutorials/topics/navigation/finite-state-ai-delegate-pattern