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

Я сделал 4 анимации за 4 GameObjects (Rockgroup_x), и я хочу начать одну анимацию случайным образом через 2 секунды, затем через 2 секунды следующую случайную анимацию и т. Д. Все анимации протестированы и работают.Сначала я устанавливаю все эти GameObjects неактивными, чтобы вы их сначала не видели, а когда они мне нужны, я активирую их в функции Rocksplants() и жду 2 секунды, а затем все начинается снова.Но coroutine не работает правильно.Я вижу только то, как игра зацикливает анимацию игрового объекта RockGroup_2.Что я делаю не так и как я могу заставить это coroutine работать?Может кто-нибудь помочь мне, пожалуйста.

Сообщение об ошибке:

NullReferenceException: ссылка на объект не установлена ​​на экземпляр объекта RocksPlants + c__Iterator0.MoveNext () (в Assets / ChosenAssets / Scripts/RocksPlants.cs:25)

(строка 25: GameObject Rockgroup_02;)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RocksPlants : MonoBehaviour {
    IEnumerator Rocksplants(){

        GameObject Rockgroup_01;
        GameObject Rockgroup_02;
        GameObject Rockgroup_03;
        GameObject Rockgroup_04;

        Rockgroup_01 = GameObject.Find("RockGroup_1");
        Rockgroup_02 = GameObject.Find("RockGroup_2");
        Rockgroup_03 = GameObject.Find("RockGroup_3");
        Rockgroup_04 = GameObject.Find("RockGroup_4");

        Rockgroup_01.SetActive(false);
        Rockgroup_02.SetActive(false); //line 25
        Rockgroup_03.SetActive(false);
        Rockgroup_04.SetActive(false);

        int rndrockgroupright = Random.Range (1, 5);

        if (rndrockgroupright == 1) {
            Rockgroup_01.SetActive (true);
            yield return new WaitForSeconds (2);
        } else if (rndrockgroupright == 2) {
            Rockgroup_02.SetActive (true);
            yield return new WaitForSeconds (2);
        } else if (rndrockgroupright == 3) {
            Rockgroup_03.SetActive (true);
            yield return new WaitForSeconds (2);
        } else if (rndrockgroupright == 4) {  
            Rockgroup_04.SetActive (true);
            yield return new WaitForSeconds (2);
        }   
    }

    // Use this for initialization
    void Start () {

    }

    // Update is called once per frame
    void Update () {
        StartCoroutine (Rocksplants());
    }
}

Ответы [ 3 ]

0 голосов
/ 30 сентября 2018

Я прочитал, что запуск сопрограммы в функции обновления вызовет проблемы, потому что каждый кадр будет запускать сопрограмму, которая должна ждать 2 секунды, поэтому я использовал функцию MonoBehaviour.InvokeRepeating, чтобы достичь своей цели, и это сработало: ->!.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RocksPlants : MonoBehaviour {

    GameObject Rockgroup_01;
    GameObject Rockgroup_02;
    GameObject Rockgroup_03;
    GameObject Rockgroup_04;


    // Use this for initialization
    void Start () {

        Rockgroup_01 = GameObject.Find("RockGroup_1");
        Rockgroup_02 = GameObject.Find("RockGroup_2");
        Rockgroup_03 = GameObject.Find("RockGroup_3");
        Rockgroup_04 = GameObject.Find("RockGroup_4");

        InvokeRepeating ("Rocksplants", 0.5f, 2.0f);

    }

    void Rocksplants() {

        Rockgroup_01.SetActive(false);
        Rockgroup_02.SetActive(false);
        Rockgroup_03.SetActive(false);
        Rockgroup_04.SetActive(false);


        int rndrockgroupright = Random.Range (1, 5);

        if        (rndrockgroupright == 1) {
            Rockgroup_01.SetActive (true);

        } else if (rndrockgroupright == 2) {
            Rockgroup_02.SetActive (true);

        } else if (rndrockgroupright == 3) {
            Rockgroup_03.SetActive (true);

        } else if (rndrockgroupright == 4) {  
            Rockgroup_04.SetActive (true);

        }   
    }
0 голосов
/ 30 сентября 2018

Ваш Coroutine вызывается в функции обновления каждый кадр.Вы можете кэшировать свой Coroutine Rocksplant и выполнить проверку обновлений, если таг подпрограмма пуста или нет, когда она пуста, вы снова вызываете подпрограмму.Вот как вы кешируете это.

Например,

private Coroutine MyRocksplantRoutine = null;

Кстати, сделайте это глобальным.Теперь в вашей функции обновления вы делаете это

Void Update()
{
    If(MyRocksplantRoutine == null)
    {
        MyRocksplantRoutine = StartCoroutine(Rocksplant());
    }
}

Таким образом, вы можете сохранить ее в функции обновления, не совершая повторный вызов.После этого вы обнуляете переменную MyRocksplantRoutine в конце сопрограммы Rocksplant следующим образом.

void IEnumerator Rocksplant()
{
    //your code
    yield return new WaitForEndOfFrame();
    MyRocksplantRoutine = null;
}
0 голосов
/ 30 сентября 2018

Я думаю, что назначение gameobjects не должно выполняться внутри метода сопрограммы.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RocksPlants : MonoBehaviour {

        GameObject Rockgroup_01;
        GameObject Rockgroup_02;
        GameObject Rockgroup_03;
        GameObject Rockgroup_04;

    IEnumerator Rocksplants(){





        Rockgroup_01.SetActive(false);
        Rockgroup_02.SetActive(false); //line 25
        Rockgroup_03.SetActive(false);
        Rockgroup_04.SetActive(false);

        int rndrockgroupright = Random.Range (1, 5);

        if (rndrockgroupright == 1) {
            Rockgroup_01.SetActive (true);
            yield return new WaitForSeconds (2);
        } else if (rndrockgroupright == 2) {
            Rockgroup_02.SetActive (true);
            yield return new WaitForSeconds (2);
        } else if (rndrockgroupright == 3) {
            Rockgroup_03.SetActive (true);
            yield return new WaitForSeconds (2);
        } else if (rndrockgroupright == 4) {  
            Rockgroup_04.SetActive (true);
            yield return new WaitForSeconds (2);
        }   
    }

    // Use this for initialization
    void Start () {
        Rockgroup_01 = GameObject.Find("RockGroup_1");
        Rockgroup_02 = GameObject.Find("RockGroup_2");
        Rockgroup_03 = GameObject.Find("RockGroup_3");
        Rockgroup_04 = GameObject.Find("RockGroup_4");
    }

    // Update is called once per frame
    void Update () {
        StartCoroutine (Rocksplants());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...