我正在制作一个项目,但我遇到了一个问题。
我有两个带有2D碰撞器的游戏对象(来自预制件),它从右向左移动。当他们互相接触时,他们会停用。
我还有一个空的游戏对象,我在其中添加一个随机生成障碍的脚本Respawner
。
问题是当他们互相接触一次时,他们再也不会重新激活了。
Respawner Empty GameObject:
边境:
public class Respawn : MonoBehaviour {
[SerializeField]
private GameObject[] obstacles;
private List<GameObject> listname = new List<GameObject>();
void Awake(){
InitilizeObstacle();
}
void Start() {
StartCoroutine(RandomObstacleSpawn());
}
void InitilizeObstacle(){
int index = 0;
for (int i=0; i<obstacles.Length * 3 ; i++) {
GameObject obj = Instantiate(obstacles[index],new Vector3(transform.position.x,transform.position.y,-2f),Quaternion.identity) as GameObject;
listname.Add(obj);
listname[i].SetActive(false);
index++;
if(index==obstacles.Length){
index =0;
}
}
}
void shuffle(){
for (int i=0; i<listname.Count; i++) {
GameObject temp = listname [i];
int random = Random.Range (i, listname.Count);
listname [i] = listname [random];
listname [random] = temp;
}
}
IEnumerator RandomObstacleSpawn(){
yield return new WaitForSeconds(Random.Range(1.5f,2.5f));
int index = Random.Range (0, listname.Count);
while (true) {
if(!listname[index].activeInHierarchy){
listname[index].SetActive(true);
listname[index].transform.position = new Vector3(transform.position.x,transform.position.y,-2f);
break;
} else {
index = Random.Range(0,listname.Count);
}
StartCoroutine(RandomObstacleSpawn());
}
}
}
脚本附加到prefab移动:
public class ObstacleMove : MonoBehaviour {
private float speed = -1.25f;
void Start() { }
void Update() {
Vector3 pos = transform.position;
pos.x += speed * Time.deltaTime;
transform.position = pos;
}
}
脚本附加到预制件上以触摸边框:
public class BorderTouch : MonoBehaviour {
void OnTriggerEnter2D(Collider2D target){
if(target.tag=="Border"){
gameObject.SetActive(false);
}
}
}
答案 0 :(得分:2)
基于新问题的新答案:
如果你想在碰撞后让事情发生。在边框上放一个脚本:
using UnityEngine;
using System.Collections;
public class borderListener : MonoBehaviour {
public Respawn rS;
void OnTriggerEnter2D(Collider2D target){
rS.spawnIt ();
}
}
在Unity Editor上,将Respawn对象拖到层次结构上的Border Script。 不要跳过这一步,否则一切都不会奏效!
在Respawn脚本上,删除StartCoroutine(RandomObstacleSpawn());
方法上的最后一个IEnumerator RandomObstacleSpawn()
行。并在Respawn脚本中创建一个公共方法(从其他脚本访问)任何地方:
public void spawnIt(){
StartCoroutine(RandomObstacleSpawn());
}
基于旧代码的旧答案:
从我在包装上看到的内容:
while (true) { //A
if(!listname[index].activeInHierarchy){
//B
listname[index].SetActive(true);
listname[index].transform.position = new Vector3(transform.position.x,transform.position.y,-2f);
break; //C
} else {
index = Random.Range(0,listname.Count);
}
StartCoroutine(RandomObstacleSpawn()); //D
}
我是一个小菜鸟,我会尽力帮助。但这段代码让我想知道:
while(true)
什么?什么是真的? (编辑:发现一些观察结果)
代码似乎是这样做的: 进入while循环(A)
转到if语句(B)中的第一个选项
去换行; (C)
永远不会到达StartCoroutine(D)&gt; 这就是为什么它不会再次激活。
如果您尝试在StartCoroutine(RandomObstacleSpawn());
之前放置break;
,您可能会遇到Unity崩溃。如果你取消while语句怎么办?你需要调整产量时间。
这是我将使用的代码:
IEnumerator RandomObstacleSpawn(){
yield return new WaitForSeconds(Random.Range(3.5f,4.5f));
int index = Random.Range (0, listname.Count);
if(!listname[index].activeInHierarchy){
listname[index].SetActive(true);
listname[index].transform.position = new Vector3(transform.position.x,transform.position.y,-2f);
}else{
index = Random.Range(0,listname.Count);
}
StartCoroutine(RandomObstacleSpawn());
}
编辑:关于while(true)我在这里找到了有关此概念的更多信息:R, How does while (TRUE) work?
但仍然......代码上的break;
实际上是对StartCoroutine(RandomObstacleSpawn());
无法访问的访问权限。
答案 1 :(得分:0)
您看到的问题相当普遍,当执行以下代码gameObject.SetActive(false);
时,它会停用该游戏对象上的所有内容。
因此,下次他们碰撞时永远不会被触发。
我不确定你想要为行为实现什么,但如果你只是想隐藏gameObjects,你可以禁用Renderer组件。
gameObject.GetComponent<SpriteRenderer>().enable = false;
并在需要时将其切换为true。
这就是为什么我们在Unity中SetActive(false)
使用gameObject
时必须小心谨慎。