3

I currently have some objects spawning from a prefab and am attempting to destroy only one of the spawned items of that prefab. I was searching online and I found tons of different examples but I have been unable to get any of them to work. I tried setting up an instance of the Instantiate and destroying that instance but I am unable to get it to work. The spawn/collision script is attached to the main camera if that matters. Collision with other items in my game work and the prefab does have a box collider set to isTrigger. Again, I know there are plenty of examples explaining this etc, but I can't get it to work and maybe I am not understanding what I actually should be doing.

Spawner code:

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 Script is on the Main Camera. Player used is the First Person Player Unity provides.

Code for destroying spawned object:

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

Destroy code is on prefab. Note prefab is not in hierarchy as it should not be.

3 Answers3

3

Firstly,

I see that you're spawning things in a for-loop and overwriting the vialss variable every time:

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

And then, on collision, you're Destroying vialss, which in this case will be the latest spawned object. And if you collide with anything after 1 collision, vialss will already be deleted and probably throw an exception. Maybe that's fine in your game, but the logic looks a bit flawed.

Also, I'm assuming you want to destroy the object you're colliding with? Does something like this not work?

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

If you, for some unrelated reason, need a list of all your spawned vials, maybe you'd like to convert that to a list instead:

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);
    }
}

Finally,

make sure that the collision detection is working. You're saying that the script is attached to your camera. please make sure you have a Collider on the camera. But you're saying that other colliders are working, so I'm guessing you have this under control.

I'd guess your issue lies in the flawed logic I initially described.

Fredrik Schön
  • 4,888
  • 1
  • 21
  • 32
  • I tried that object Destroy before I tried this solution using the vialss. And yes my script is on the camera. However, the collision script is part of the spawn script, therefore, the collision is not on the item I am colliding with. I do not have the script on the prefab because for one, it is not in the hierarchy even though that should make no difference. But more importantly, two, I am not sure how to check if the vialss are being collided with from a separate script. The vialss are being defined in the spawn and I would need to somehow use that in the collision. –  Mar 18 '19 at 16:02
  • And thank you for noting the use of a list, and I will use it once I am able to get the collision working –  Mar 18 '19 at 16:03
  • What prevents you from doing it the normal way? Adding the OnTriggerEnter on the object that is actually a part of the collision? – Fredrik Schön Mar 18 '19 at 19:24
  • If I take the void on collider example that you provided which is usually what I originally used, place it in a script by itself and attach that script to the prefab it does nothng upon collision –  Mar 18 '19 at 20:17
  • I'm guessing that neither of the objects doesn't have a rigidbody, thus not enabling collision detection. If you don't want physics on the object, simply tic the settings in the rigidbody to not be physically simulated. – Fredrik Schön Mar 18 '19 at 22:39
  • This is getting to be a long convo for the comment section. But I have a box collider set to is trigger on the vial with mesh collider disabled, enabled or disabled makes no difference in working. I have this same thing set up on a stable non-moving GameObject within the world and that collision is working just fine. Same code used for Destroy everything. Double checked to see if tag was correct and everything. I don't see what could be wrong anywhere. Even deleted and remade prefab just to make sure. –  Mar 19 '19 at 00:01
  • Have you made sure that one of the objects has a Rigidbody? They won't trigger unless one of the objects [has a Rigidbody.](https://docs.unity3d.com/ScriptReference/Collider.OnTriggerEnter.html) – Fredrik Schön Mar 19 '19 at 15:55
  • 1
    The player currently has a Rigidbody on it, vial has box collider with isTrigger set that's essentially the setup –  Mar 20 '19 at 01:40
  • So the OnTriggerEnter code should be on the player, not the camera. – Fredrik Schön Mar 20 '19 at 15:22
  • It is on the vial, I took the tip to split the scripts so I did. The script for the spawning of the item is on the camera. The vial (the prefab which is nowhere in the hierarchy as it has no use there) has its own script attached to it (the destroy code containing the OnTriggerEnter). If you wish I could edit the question displaying how and where everything is set up. –  Mar 20 '19 at 17:24
  • I got this working. I did have to create an additional Rigidbody on the object to destroy so it had a box collider with isTrigger and a RigidBody. Creating the list also worked well although sometimes registering the collision is a bit slow, but, that's maybe because I have so many spawning at a time. –  Mar 23 '19 at 13:48
1

OnTriggerEnter needs to be on a script attached to the object it's colliding with, or the vial itself. It can't be on the main camera as OnTriggerEnter will never get called.

Brandon Miller
  • 1,534
  • 1
  • 11
  • 16
  • How would I do this considering the prefab is technically not in the scene? I could add a simple collision to it still but then how would I call the instance from the other script to check if it has collided with it. (The instance being vialss) –  Mar 18 '19 at 14:39
0

I would recommend you to keep scripts to one job, you should split that script into a Spawn script and a Collider script. And create a empty GameObject with the sole purpose of spawning prefabs. Also there's some errors in your code:

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

Also the variable vialss isn't doing what you're expecting, vialss is only referencing to the last instantiated vial, so better save all vials in a List:

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

And then:

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