我已经用4 GameObjects (Rockgroup_x)
制作了4个动画,我想在2秒后随机开始一个动画,然后在2秒后随机开始下一个随机动画,等等。所有动画都经过测试并可以工作。首先,我将所有这些GameObjects
设置为非活动状态,这样一开始您就不会看到它们,当我需要它们时,我将它们在功能Rocksplants()
中设置为活动状态并等待2秒钟,然后重新开始。但是coroutine
无法正常工作。我只看到游戏在循环播放RockGroup_2 GameObject的动画。我在做什么错?如何使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());
}
}
答案 0 :(得分:1)
我认为游戏对象的分配不应该在协程方法中完成。
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());
}
}
答案 1 :(得分:1)
我读到在更新函数中启动协程会引起问题,因为它将在每一帧中启动协程,等待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);
}
}
答案 2 :(得分:0)
每帧在Update函数中调用您的协程。您可能想要缓存Coroutine Rocksplant并进行更新检查,例如thag例程是否为null,因此当其无效时,您可以再次调用该例程。这是yoi缓存它的方式。
例如
private Coroutine MyRocksplantRoutine = null;
将其设为全局。 现在,在更新功能上,您可以执行此操作
Void Update()
{
If(MyRocksplantRoutine == null)
{
MyRocksplantRoutine = StartCoroutine(Rocksplant());
}
}
这样,您可以将其保留在更新功能中,而无需对其进行重复调用。之后,像这样,在Rocksplant Coroutine的末尾将变量MyRocksplantRoutine设置为空。
void IEnumerator Rocksplant()
{
//your code
yield return new WaitForEndOfFrame();
MyRocksplantRoutine = null;
}