Запустите сопрограмму на неактивном / деактивированном GameObject - PullRequest
0 голосов
/ 26 октября 2018

У меня есть следующий код:

void Start()
{
    gameObject.SetActive(false);
    StartCoroutine(Load());
}

IEnumerator Load()
{
    yield return new WaitForSeconds(waitTime);
    gameObject.SetActive(true);
}

Это дает мне сообщение об ошибке:

Не удалось запустить Coroutine, потому что игровой объект NameOfObjinactive!

Это имеет смысл, поскольку игровой объект был настроен на деактивацию перед запуском скрипта.И все же, что мне тогда делать?Я пытался переместить gameObject.SetActive(false) к сопрограмме до WaitForSeconds().Это вообще остановило загрузку игрового объекта.

Насколько я понимаю, когда исполняется строка gameObject.SetActive(false), сценарий останавливается, пока игровой объект не будет реактивирован.Однако, если это так, разве не было бы невозможно затем повторно активировать игровой объект (так как скрипт отключен)?

Независимо от того, как бы я отложил загрузку игрового объекта до 2-3 (илипроизвольный промежуток времени) после начала игры?

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Вы не можете запустить функцию сопрограммы из сценария, у которого деактивирован GameObject.

Функция StartCoroutine является функцией класса MonoBehaviour.Когда вам нужно запустить сопрограмму на деактивированном GameObject, вам нужна ссылка на MonoBehaviour объект с активным GameObject.

Два способа сделать это :

1 .Используйте уже существующий GameObject, который вряд ли будет деактивирован.В моем случае я обычно использую камеру.Я получаю доступ к камере MonoBehaviour, поскольку она, вероятно, будет активирована, а затем использую ее для запуска функции сопрограммы.

Я предлагаю вам использовать этот метод.

Замените код в вашей функции Start на приведенный ниже:

//De-activate this GameObject
gameObject.SetActive(false);
//Get camera's MonoBehaviour
MonoBehaviour camMono = Camera.main.GetComponent<MonoBehaviour>();
//Use it to start your coroutine function
camMono.StartCoroutine(Load());

2 .Прикрепите скрипт к пустому GameObject, и скрипт на пустом GameObject будет контролировать или иметь возможность активировать / деактивировать другой GameObject.

Скрипт с функцией сопрограммы, которую вы ожидаете запустить на деактивированнойGameObject (прикрепите его к GameObject, который вы хотите деактивировать):

public class YourDeactivatableScript: MonoBehaviour
{
    public IEnumerator Load()
    {
        yield return new WaitForSeconds(waitTime);
        gameObject.SetActive(true);
    }
}

Теперь предположим, что вы хотите деактивировать GameObject с именем "Cube" , который имеет YourDeactivatableScript прикрепленный к нему сценарий, но все еще в состоянии запустить его функцию сопрограммы Load, создать пустой GameObject с новым сценарием, а затем запустить из него функцию Load.

Создать пустой GameObject и затем присоединить этот сценарий кit:

public class LoadFuncCallerScript: MonoBehaviour
{
    GameObject targetObject;

    public void Start()
    {
         //Find the GameObject you want to de-activate
        targetObject = GameObject.Find("Cube");
        //De-activate it
        targetObject.SetActive(false);
        //Get it's component/script
        YourDeactivatableScript script = targetObject.GetComponent<YourDeactivatableScript>();
        //Start coroutine on the other script with this MonoBehaviour
        StartCoroutine(script.Load());
    }
}

Сопрограмма теперь запускается из другого скрипта с именем LoadFuncCallerScript.

0 голосов
/ 26 октября 2018

То, что я делаю, чтобы избежать остановки сопрограмм, это наличие игрового объекта, который не деактивируется.

public class CoroutineHandler : MonoBehaviour
{
    private static CoroutineHandler instance = null;
    public static CoroutineHandler Instance
    {
        get
        {
            if(instance == null)
            {
                GameObject inst = new GameObject("CoroutineHandler");
                DontDestroyOnLoad(inst);
                instance = inst.AddComponent<CoroutineHandler>();
            }
            return instance;
        }
    }
}

Затем используйте его для таких сопрограмм, используя CoroutineHandler.Instance.StartCoroutine(RoutineMethodHere());.

Если выне хотите что-то подобное, так как это может пойти не так или вызвать утечку, если не обрабатывается правильно, вы можете попробовать использовать Invoke("MethodName", delay);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...