如果目标未受到损坏或到达距起始位置的最大允许距离,则将目标发送回起始位置

时间:2019-01-02 18:44:07

标签: unity3d

如果没有造成伤害或到达起始位置的最大允许距离,我会尝试将目标送回到起始位置时遇到问题。 现在,当目标达到最大允许距离时,他便冻结并等待直到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);
    }
}

1 个答案:

答案 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");
        }
    }
}