关于c#:与对象碰撞时,Prefab无法激活

Prefab doesnot activate when collide with object

我正在做一个项目,我遇到了一个问题。

我有两个带有2D对撞机(来自预制件)的gameObject,它们从右向左移动。当它们彼此接触时,它们将被禁用。

我还有一个空的游戏对象,其中添加了一个脚本Respawner,该脚本随机生成障碍物。

问题是当他们彼此接触一次时,他们再也不会被重新激活。

Respawner Empty GameObject:

enter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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());
        }
    }
}

脚本附加到预制件上以进行移动:

1
2
3
4
5
6
7
8
9
10
11
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;  
    }
}

脚本附加到用于触摸边框的预制件:

1
2
3
4
5
6
7
public class BorderTouch : MonoBehaviour {
    void OnTriggerEnter2D(Collider2D target){
            if(target.tag=="Border"){
            gameObject.SetActive(false);
        }
    }
}


基于新问题的新答案:

如果您想让事情在碰撞后发生。将脚本放在Border:

1
2
3
4
5
6
7
8
9
10
11
12
using UnityEngine;
using System.Collections;

public class borderListener : MonoBehaviour {
        public Respawn rS;

        void OnTriggerEnter2D(Collider2D target){
                rS.spawnIt ();

        }

}

在Unity Editor上,将Respawn对象拖动到层次结构上的Border Script。
不要跳过此步骤,否则事情将不起作用!

在Respawn脚本上,删除IEnumerator RandomObstacleSpawn()方法上的最后StartCoroutine(RandomObstacleSpawn());行。并在Respawn脚本内的任意位置创建一个公共方法(以从其他脚本访问):

1
2
3
public void spawnIt(){
                StartCoroutine(RandomObstacleSpawn());
        }

基于旧代码的旧答案:

根据您在包裹上看到的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
    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)>,这就是为什么它不会再次激活的原因。

如果尝试将StartCoroutine(RandomObstacleSpawn());放在break;之前,则可能会导致Unity崩溃。如果您完全删除了while语句,该怎么办?您需要调整屈服时间tho。

这是我要使用的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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,while(TRUE)如何工作?
但是,仍然...代码上的break;确实使对StartCoroutine(RandomObstacleSpawn());的访问无法实现。


您所看到的问题相当普遍,当执行以下代码gameObject.SetActive(false);时,该游戏对象上的所有内容均将失效。

因此,下次发生碰撞时将永远不会触发。

我不确定您要为该行为实现什么,但是如果您只想隐藏gameObjects,则可以禁用Renderer组件。

1
gameObject.GetComponent<SpriteRenderer>().enable = false;

并在需要时将其切换为true。

这就是为什么我们在Unity中的gameObject上使用SetActive(false)时必须谨慎的原因。