Проклятые Корутины

Форум для самых маленьких, а так же тех, кому недосуг читать справку самостоятельно.

Проклятые Корутины

Сообщение egorych8 15 сен 2020, 14:46

Подскажите как в этом скрипте победить корутины.
Задача такая - объект Враг патрулирует по списку точек с координатами. Это задается с помощью вызова корутины FollowPath.
Помимо этого по полю перемещается другой объект Player. Когда враг видит player - он должен начать преследовать его, тут я подключаю NavMesh, но после того как враг теряет player из виду он должен вернуться исполнению скрипта в корутине, т.е. патрулированию.
У меня он перестает двигаться, после того как дойдёт до точки в которой последний раз видел player.
Как я понимаю корутина в данном случае запускается из метода Start и поэтому только один раз проходит.


Синтаксис:
Используется csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class Guard : MonoBehaviour
{
    public static event System.Action OnGuardHasSpottedPlayer;
    public float speed = 5f;
    public float waitTime = .3f;
    public float turnSpeed = 90;
    public float timeToSpotPlayer = 1f;
    public Light spotlight;
    public float viewDistance;
    public LayerMask viewMask;
    float viewAngle;
    float playerVisibleTimer;
    public Transform pathHolder;
    Transform player;
    Color originalSpotLightColour;
    public Transform MyPlayer;
    private NavMeshAgent myAgent;
    private bool corout;
    void Start()
       
    {
        myAgent = GetComponent<NavMeshAgent>();
        player = GameObject.FindGameObjectWithTag("Player").transform;
        viewAngle = spotlight.spotAngle;
        originalSpotLightColour = spotlight.color;
        Vector3[] waypoints = new Vector3[pathHolder.childCount];
        for (int i = 0; i < waypoints.Length; i++)
        {
            waypoints[i] = pathHolder.GetChild(i).position;
            waypoints[i] = new Vector3(waypoints[i].x, transform.position.y, waypoints[i].z);
            }
         StartCoroutine(FollowPath(waypoints));
    }
    private void Update()
    {
        if (CanSeePlayer())
        {
            playerVisibleTimer += Time.deltaTime;
        }
        else
        {
            playerVisibleTimer -= Time.deltaTime;
        }
        spotlight.color = Color.Lerp(originalSpotLightColour, Color.red, playerVisibleTimer / timeToSpotPlayer);
        playerVisibleTimer = Mathf.Clamp(playerVisibleTimer, 0, timeToSpotPlayer);
        if (playerVisibleTimer >= timeToSpotPlayer)
        {
            if (OnGuardHasSpottedPlayer != null)
            {
                OnGuardHasSpottedPlayer();
            }
            //myAgent.SetDestination (MyPlayer.transform.position);
        }
    }
 
 
     bool CanSeePlayer()
    {
        if (Vector3.Distance(transform.position, player.position) < viewDistance)
        {
            Vector3 dirToPlayer = (player.position - transform.position).normalized;
            float angleBetweenGuardAndPlayer = Vector3.Angle(transform.forward, dirToPlayer);
            if (angleBetweenGuardAndPlayer < viewAngle / 2f)
            {
                if (!Physics.Linecast(transform.position, player.position, viewMask))
                {
                    return true;
                }
            }
        }
        return false;
    }
    private IEnumerator FollowPath(Vector3[] waypoints)
    {
     
        transform.position = waypoints[0];
            int targetWaypointIndex = 1;
            Vector3 targetWaypoint = waypoints[targetWaypointIndex];
            transform.LookAt(targetWaypoint);
            while (true)
            {
            transform.position = Vector3.MoveTowards(transform.position, targetWaypoint, speed * Time.deltaTime);
                if (transform.position == targetWaypoint)
                {
                    targetWaypointIndex = (targetWaypointIndex + 1) % waypoints.Length;
                    targetWaypoint = waypoints[targetWaypointIndex];
                    yield return new WaitForSeconds(waitTime);
                    yield return StartCoroutine(TurnToFace(targetWaypoint));
                }
                yield return null;
            }
    }

    private IEnumerator TurnToFace(Vector3 lookTarget)
    {
        Vector3 dirToLookTarget = (lookTarget - transform.position).normalized;
        float targetAngle = 90 - Mathf.Atan2(dirToLookTarget.z, dirToLookTarget.x) * Mathf.Rad2Deg;
        while (Mathf.Abs(Mathf.DeltaAngle(transform.eulerAngles.y, targetAngle)) > 0.05f)
        {
            float angle = Mathf.MoveTowardsAngle(transform.eulerAngles.y, targetAngle, turnSpeed * Time.deltaTime);
            transform.eulerAngles = Vector3.up * angle;
            yield return null;
        }
    }
egorych8
UNIт
 
Сообщения: 71
Зарегистрирован: 28 июл 2020, 16:06

Re: Проклятые Корутины

Сообщение Saltant 15 сен 2020, 15:11

Запускай корутину патруля когда враг потерял игрока из виду, че тут сложного. Останавливаешь корутину когда начинается преследование, стартуешь корутину когда заканчивается преследование.
Я на Google Play _https://play.google.com/store/apps/developer?id=Saltant
Аватара пользователя
Saltant
Адепт
 
Сообщения: 2235
Зарегистрирован: 09 окт 2018, 16:40
Откуда: Химки
  • Сайт

Re: Проклятые Корутины

Сообщение egorych8 15 сен 2020, 17:01

Если я вызываю корутину из метода Update, то ругается на аргумент корутины.
Если можешь напиши конкретнее как это сделать?
egorych8
UNIт
 
Сообщения: 71
Зарегистрирован: 28 июл 2020, 16:06

Re: Проклятые Корутины

Сообщение Saltant 15 сен 2020, 17:38

Update выполняется каждый кадр, там не нужно запускать корутины.
Я на Google Play _https://play.google.com/store/apps/developer?id=Saltant
Аватара пользователя
Saltant
Адепт
 
Сообщения: 2235
Зарегистрирован: 09 окт 2018, 16:40
Откуда: Химки
  • Сайт

Re: Проклятые Корутины

Сообщение egorych8 16 сен 2020, 14:06

Так как тогда два раза вызвать из Start два раза корутину? Сами себе противоречите
egorych8
UNIт
 
Сообщения: 71
Зарегистрирован: 28 июл 2020, 16:06

Re: Проклятые Корутины

Сообщение Saltant 16 сен 2020, 14:09

egorych8 писал(а):Так как тогда два раза вызвать из Start два раза корутину? Сами себе противоречите

Кавооо?
Корутины: https://habr.com/ru/post/442622/
Я на Google Play _https://play.google.com/store/apps/developer?id=Saltant
Аватара пользователя
Saltant
Адепт
 
Сообщения: 2235
Зарегистрирован: 09 окт 2018, 16:40
Откуда: Химки
  • Сайт

Re: Проклятые Корутины

Сообщение egorych8 16 сен 2020, 15:10

Saltant писал(а):Запускай корутину патруля когда враг потерял игрока из виду, че тут сложного. Останавливаешь корутину когда начинается преследование, стартуешь корутину когда заканчивается преследование.

Ок, распишу подробнее -
условие проверки видимости врагом игрока будет выполняться в Update. Значит и запускать и останавливать корутину нужно из Update.
Верно?
И если это будет одна и таже корутина, как тогда враг после потери игрока будет возвращаться к патрулированию, но не с первой точки, а с ближайшей ?

По ссылке я не нашёл ответов
egorych8
UNIт
 
Сообщения: 71
Зарегистрирован: 28 июл 2020, 16:06

Re: Проклятые Корутины

Сообщение Saltant 16 сен 2020, 15:12

egorych8 писал(а):
Saltant писал(а):Запускай корутину патруля когда враг потерял игрока из виду, че тут сложного. Останавливаешь корутину когда начинается преследование, стартуешь корутину когда заканчивается преследование.

как тогда враг после потери игрока будет возвращаться к патрулированию, но не с первой точки, а с ближайшей ?

Произвести поиск ближайшей точки в массиве вейпоинтов после потери игрока и начать с неё.
Я на Google Play _https://play.google.com/store/apps/developer?id=Saltant
Аватара пользователя
Saltant
Адепт
 
Сообщения: 2235
Зарегистрирован: 09 окт 2018, 16:40
Откуда: Химки
  • Сайт

Re: Проклятые Корутины

Сообщение egorych8 16 сен 2020, 15:18

Saltant писал(а):Запускай корутину патруля когда враг потерял игрока из виду, че тут сложного. Останавливаешь корутину когда начинается преследование, стартуешь корутину когда заканчивается преследование.




Распишу подробнее -
условие проверки видимости врагом игрока будет выполняться в Update. Значит и запускать и останавливать корутину нужно из Update.
Верно?
Можете в примере коде указать куда что поставить?
egorych8
UNIт
 
Сообщения: 71
Зарегистрирован: 28 июл 2020, 16:06

Re: Проклятые Корутины

Сообщение Saltant 16 сен 2020, 20:55

egorych8 писал(а):
Saltant писал(а):Запускай корутину патруля когда враг потерял игрока из виду, че тут сложного. Останавливаешь корутину когда начинается преследование, стартуешь корутину когда заканчивается преследование.

условие проверки видимости врагом игрока будет выполняться в Update. Значит и запускать и останавливать корутину нужно из Update.
Верно?

Нет. Запускать и останавливать корутину можешь откуда угодно. Можешь ваще какой нить EnemyMoveController сделать и там уже писать всю логику работы врагов, кто куда двигается, кто чё делает, они (враги) будут передавать сигналы в этот контроллер, а контроллер уже выполнять какие то действия с этими болванчиками.
Я на Google Play _https://play.google.com/store/apps/developer?id=Saltant
Аватара пользователя
Saltant
Адепт
 
Сообщения: 2235
Зарегистрирован: 09 окт 2018, 16:40
Откуда: Химки
  • Сайт


Вернуться в Почемучка

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex [Bot] и гости: 31