产生碰撞后销毁预制对象

时间:2019-03-18 14:11:38

标签: unity3d objectinstantiation object-destruction

我目前有一些物体是从预制件中产生的,并且正在尝试销毁该预制件中产生的一件物品。我在网上搜索,发现了很多不同的示例,但我一直无法使它们工作。我尝试设置实例化实例并销毁该实例,但无法使其正常工作。如果重要的话,派生/碰撞脚本将附加到主摄像头。与游戏工作中的其他项目发生碰撞,并且预制件确实将盒碰撞器设置为isTrigger。再说一次,我知道有很多例子可以解释这一点,但我无法使其正常工作,也许我不了解我应该实际做什么。

扳手代码:

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

public class bloodVialSpawner : MonoBehaviour
{
    public GameObject vialOfBlood;
    private GameObject vialss;
    private int hunger =10;
    public int numOfVials;
    public int minSpawnRange, maxSpawnRange;
    public int minSpawnRange2, maxSpawnRange2;
    // Start is called before the first frame update
    float timeSpawns = 2;
    List<GameObject> vialsInstantiated = new List<GameObject>();
    void Start()
    {
        StartCoroutine(becomeHungry());
        InvokeRepeating("SpawnVials", timeSpawns, timeSpawns);
    }
    private void Update()
    {
        if (hunger == -1)
        {
            Debug.Log("sigh");
        }
    }
    void SpawnVials()
    {
        for (int i = 0; i < numOfVials; i++)
        {
            vialsInstantiated.Add(Instantiate(vialOfBlood, SpawnPosition(), Quaternion.identity) as GameObject);
        }
    }
    Vector3 SpawnPosition()
    {
        int x, y, z;
        y = 59;
        x= UnityEngine.Random.Range(minSpawnRange, maxSpawnRange);
        z = UnityEngine.Random.Range(minSpawnRange2, maxSpawnRange2);
        return new Vector3(x, y, z);
    }

    IEnumerator becomeHungry()
    {
        while (true)
        {
            hunger -= 1;
            yield return new WaitForSeconds(1);
            Debug.Log(hunger);
        }
    }
}

enter image description here

Spawner脚本位于主摄像机上。使用的播放器是Unity提供的第一人称播放器。

销毁生成的对象的代码:

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

public class destroyVial : MonoBehaviour
{
    void OnTriggerEnter(Collider col)
    {
        if (col.gameObject.tag == "vials")
        {
            Destroy(col.gameObject);
            Debug.Log("yell");
        }
    }
}

enter image description here

销毁代码在预制件上。请注意,预制件不是应有的层次结构。

3 个答案:

答案 0 :(得分:3)

首先,

我看到您每次都在for循环中生成事物并覆盖vialss变量:

for (int i = 0; i < numOfVials; i++)
{
   vialss = Instantiate(vialOfBlood, 
                        SpawnPosition(),
                        Quaternion.identity) as GameObject;
}

然后,在发生冲突时,您将销毁vialss,在这种情况下,它将是最新生成的对象。并且,如果您在1次碰撞后与任何物体发生碰撞,vialss将被删除,并且可能引发异常。也许这在您的游戏中很好,但是逻辑看起来有些瑕疵。

此外,我假设您想销毁与之碰撞的物体?这样的东西行不通吗?

void OnTriggerEnter(Collider col)
{
    if (col.gameObject.tag == "vials")
    {
        Destroy(col.gameObject); // <== Remove colliding object
        Debug.Log("yell");
    }
}

如果出于某种不相关的原因,您需要所有产卵瓶的列表,也许您想将其转换为列表:

List<GameObject> spawnedVials = new List<GameObject>();

void SpawnVials()
{
    for (int i = 0; i < numOfVials; i++)
    {
        var vial = Instantiate<GameObject>(vialOfBlood,
                                         SpawnPosition(),
                                         Quaternion.identity)
        spawnedVials.Add(vial);
    }
}

最后,

确保碰撞检测正常。您是说脚本已附加到相机上。请确保相机上有对撞机。但是您是说其他对撞机正在工作,所以我想您已经对此进行了控制。

我猜你的问题出在我最初描述的错误逻辑中。

答案 1 :(得分:1)

OnTriggerEnter必须位于与碰撞对象或小瓶本身相连的脚本上。它不能在主摄像机上,因为永远不会调用OnTriggerEnter。

答案 2 :(得分:0)

我建议您将脚本保留为一项工作,您应该将该脚本分为Spawn脚本和Collider脚本。并创建一个空的GameObject,其唯一目的是生成预制件。 您的代码中也有一些错误:

    void OnTriggerEnter(Collider col)
    {
        if (col.gameObject.tag == "vials")
        {
            Destroy(col.gameObject); // Destroy the gameObject you're colliding with
            Debug.Log("yell");
        }
    }

变量小瓶也无法满足您的期望,小瓶仅引用最后实例化的小瓶,因此最好将所有小瓶保存在列表中:

    List<GameObject> vialsInstantiated = new List<GameObject>();

然后:

    void SpawnVials()
    {
        for (int i = 0; i < numOfVials; i++)
        {
            vialsInstantiated.Add(Instantiate(vialOfBlood, SpawnPosition(), Quaternion.identity) as GameObject);
        }
    }