如果没有造成伤害或到达起始位置的最大允许距离,我会尝试将目标送回到起始位置时遇到问题。 现在,当目标达到最大允许距离时,他便冻结并等待直到Couroutine结束计数时间。但我要他立即回来。
这是我正在使用的代码。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.AI;
[RequireComponent(typeof(NavMeshAgent))]
public class DFieldOfView : MonoBehaviour
{
NavMeshAgent agent;
public Transform startingPoint;
public float maxAttackDistance = 3;
public float maxAllowedDistance = 10f;
public float viewRadius; // matymo laukas
[Range(0, 360)] // Range nuo iki
public float viewAngle; // matymo kampas
[SerializeField] private LayerMask targetMask;
public LayerMask obstacleMask;
[SerializeField] private float rotatingSpeed = 20f;
//[SerializeField] ParticleSystem fireEffect;
[HideInInspector] public float dstToTarget;
[HideInInspector] public List<Transform> visibleTargets = new List<Transform>();
Transform targets;
EnemyHealth health;
private Animator anim;
private new AudioSource audio;
//private bool isShootReady = false;
Vector3 dirToTarget;
bool targetunset = true;
//bool sound_playing = false;
Quaternion rotation;
public float totalDuration = 3f;
public bool isDamageActivated = false;
//public float SoundTime = 3f;
void Start()
{
health = GetComponent<EnemyHealth>();
agent = GetComponent<NavMeshAgent>();
anim = GetComponent<Animator>();
//audio = GetComponent<AudioSource>();
}
private void Update()
{
if (isDamageActivated)
{
FindVisableTarget();
StartCoroutine(AgroRoutine(targets));
}
Debug.Log("Damage was dealt: " + isDamageActivated);
}
void FindVisableTarget() // Rasti matomus taikinius
{
visibleTargets.Clear(); // istrina lista
Collider[] targetsInViewRadius = Physics.OverlapSphere(transform.position, viewRadius, targetMask); // grazina visus taikinius kurie ieina i matymo lauka
for (int i = 0; i < targetsInViewRadius.Length; i++) // matomi tainkiniai
{
targets = targetsInViewRadius[i].transform; // Taikiniai matymo lauke
if (targetunset) { SetTarget(targets); }
dirToTarget = (targets.position - transform.position).normalized; // kryptis i taikini
if (Vector3.Angle(transform.forward, dirToTarget) < viewAngle / 2) // ar taikinys yra matomumo zonoi
{
dstToTarget = Vector3.Distance(transform.position, targets.position); //distancija iki taikinio
if (!Physics.Raycast(transform.position, dirToTarget, dstToTarget, obstacleMask)) // nera jokiu kliuciu ir taikinys matomas
{
Rotating();
visibleTargets.Add(targets);
}
}
}
}
//IEnumerator AgroRoutine(Transform target)
//{
// float distance = Vector3.Distance(transform.position, startingPoint.position);
// if (targets != null)
// {
// if ((transform.position - startingPoint.position).magnitude < maxAllowedDistance)
// {
// MoveTo(targets.position);
// anim.SetBool("isRuning", true);
// if (maxAttackDistance <= dstToTarget)
// {
// Debug.Log(dstToTarget);
// anim.SetBool("isAttacking", true);
// }
// else
// {
// anim.SetTrigger("idle");
// }
// Debug.Log("Target not null and in range");
// }
// else if ((transform.position - startingPoint.position).magnitude > maxAllowedDistance)
// {
// Debug.Log("Target null and/or out of range");
// yield return new WaitForSeconds(agroDuration);
// MoveTo(startingPoint.position);
// yield return new WaitForSeconds(3f);
// anim.SetTrigger("idle");
// }
// }
//}
IEnumerator AgroRoutine(Transform target)
{
if (target != null)
{
MoveTo(targets.position);
anim.SetBool("isRuning", true);
if (maxAttackDistance >= dstToTarget)
{
Debug.Log("Attacking");
agent.isStopped = true;
anim.SetBool("isAttacking", true);
}
else
{
anim.SetTrigger("idle");
}
Debug.Log("Target not null and in range");
totalDuration = 3f; // 3 seconds. You can change this to whatever you want
float timer = 0;
while (timer <= totalDuration)
{
// Check for maximum allowed distance
float distance = Vector3.Distance(transform.position, startingPoint.position);
if (distance >= maxAllowedDistance || distance >= MonsterField.radius)
Return(startingPoint.position);
Debug.Log("Distance more than allowed distance " + (distance > maxAllowedDistance || distance >= MonsterField.radius));
// Your object can keep moving. Increment timer and check again on the next frame
timer += Time.deltaTime;
yield return null;
}
}
}
public void Return(Vector3 point)
{
MoveTo(point);
anim.SetTrigger("idle");
}
IEnumerator DamageStopRoutine()
{
yield return new WaitForSeconds(totalDuration);
isDamageActivated = false;
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Bullet")
{
isDamageActivated = true; // damage activated
Destroy(other.gameObject);
TakeHP(BulletDamage.currentBulletDmg);
}
StartCoroutine(DamageStopRoutine());
}
public void MoveTo(Vector3 point)
{
agent.SetDestination(point);
}
public Vector3 DirFromAngle(float angleInDegrees, bool angleIsGlobal)
{
if (!angleIsGlobal)
{
angleInDegrees += transform.eulerAngles.y;
}
return new Vector3(Mathf.Sin(angleInDegrees * Mathf.Deg2Rad), 0, Mathf.Cos(angleInDegrees * Mathf.Deg2Rad));
}
public void SetTarget(Transform targets)
{
targetunset = false;
dirToTarget = (targets.position - transform.position).normalized; // kryptis i taikini
rotation = Quaternion.LookRotation(dirToTarget);
Invoke("UnsetTarget", 0.05f);
}
public void Rotating()
{
transform.rotation = Quaternion.Slerp(transform.rotation, rotation, Time.deltaTime * rotatingSpeed);
}
public void UnsetTarget()
{
targetunset = true;
}
//public void PlayingSound()
//{
// audio.Play();
// sound_playing = true;
// Invoke("StoppingSound", SoundTime);
//}
//public void StoppingSound()
//{
// audio.Stop();
// sound_playing = false;
//}
public void TakeHP(float dmg)
{
health.initialHP -= dmg;
// hit animation
anim.SetTrigger("hit");
new WaitForSeconds(1f);
anim.SetTrigger("idle");
if (health.initialHP <= 0)
{
Die();
}
}
void Die()
{
// animation
anim.SetBool("isAttacking", false);
anim.SetBool("isDied", true);
Destroy(gameObject, 2f);
}
}
答案 0 :(得分:0)
您需要将运动逻辑与停止逻辑分开。正常移动对象,并将协程用作停止逻辑。我已经根据您的两个标准对时间进行了修改:时间和距离。
IEnumerator AgroRoutine(Transform target)
{
if (target != null)
yield return break;
float totalDuration = 3f; // 3 seconds. You can change this to whatever you want
float timer = 0;
while (timer <= totalDuration)
{
// Check for maximum allowed distance
float distance = Vector3.Distance(transform.position, startingPoint.position);
if (distance > maxAllowedDistance)
Return(startingPoint.position);
// Your object can keep moving. Increment timer and check again on the next frame
timer += Time.deltaTime;
yield return null;
}
}
public void Return (Vector3 point)
{
MoveTo(point);
anim.SetTrigger("idle");
}
您告诉协程,要等3秒才能移动。如果您不希望发生这种情况,请删除该行。
public float agroDuration = 3f;
IEnumerator AgroRoutine(Transform target)
{
...
else if ((transform.position - startingPoint.position).magnitude > maxAllowedDistance)
{
Debug.Log("Target null and/or out of range");
yield return new WaitForSeconds(agroDuration);
MoveTo(startingPoint.position);
yield return new WaitForSeconds(3f);
anim.SetTrigger("idle");
}
}
}