Not sure what I did but I can destroy multiple packages now

So, somehow, after finishing the code for this section and succesfully changing my car’s color, I can now destroy all packages by passing over them whether or not I “hasPackage”, though if I do “hasPackage”, while it still destroys the package it does not print the confirmation that I picked it up to console.

Hi!

Helping you without seeing your code is quite hard, Could you please copy-paste your code in this thread so we can see it?

Hi,

Have you already compared your code to the Lecture Project Changes which can be found in the Resources of this lecture? If so, please share your code as suggested by Yee.


See also:

Sorry for the late reply, I lost my internet for a bit. I compared my code, and the only real difference I can spot is a small portion I added to destroy customers on delivery as well. Here’s my code:

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

public class Delivery : MonoBehaviour
{
    [SerializeField] Color32 hasPackageColor = new Color32 (1, 1, 1, 1);
    [SerializeField] Color32 noPackageColor = new Color32 (1, 1, 1, 1);
    [SerializeField] float destroySpeed = 0.5f;

    bool hasPackage;

    SpriteRenderer spriteRenderer;

    void Start()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
    }


    void OnCollisionEnter2D(Collision2D other) 
    {
         Debug.Log("JESUS Ricky! You been drinkin?!");
    }
    void OnTriggerEnter2D(Collider2D other) 
    {
        if (other.tag == "Package" && !hasPackage) 
        {
             Debug.Log("Hope that wasn't fragile...");
             hasPackage = true;
             Destroy(other.gameObject, destroySpeed);
             spriteRenderer.color = hasPackageColor;
         }
        if (other.tag == "Customer" && hasPackage)
        {
            Debug.Log("Here's yah friggin box of crap!");
            hasPackage = false;
            Destroy(other.gameObject, destroySpeed);
        }   spriteRenderer.color = noPackageColor;
    }
}

Welcome back, and Happy New Year! :slight_smile:

Your code looks fine to me but it might be that Destroy is causing the problem(s).

Add the following in your if-statements:

other.gameObject.SetActive(false);

Since Destroy does not destroy an object immediately but at the end of the frame, it might be that the car collides with the “not yet destroyed” package again. By disabling the game object you want to destroy, it cannot be found anymore.

In your code, you use destroySpeed. If you want to destroy the game object with a delay, disable its collider instead of disabling the entire game object, so the car does not interact with the package (or customer) anymore.

other.GetComponent<BoxCollider2D>().enabled = false;

If you are missing messages in your console, click on the “Collapse” button in the Console window. Maybe your messages are not missing but “collapsed”.

Either I’m misunderstanding, or I think you may have misunderstood. The issue isn’t with a single package being triggered twice or something like that, the issue is that I have multiple packages on the map, and multiple customers. If I pick up a package, and I do not “hasPackage”, it is set to destroy the object, and change “hasPackage” to “true”. While “hasPackage” is “true”, it should no longer destroy any packages, as I have not coded it to. However, while “hasPackage” is true, any other package I drive over gets destroyed as if I do NOT “hasPackage”, as if I have coded it to destroy on “hasPackage”, though I have not. And when any subsequent package is destroyed while I “hasPackage”, nothing prints to console because I haven’t coded anything to print to console when I drive over a package while I “hasPackage”, just like it shouldn’t destroy. But it does anyway. And all of the packages have the same code, to be destroyed, print to console and change “hasPackage” true, ONLY if “hasPackage” is false to begin with. For some reason they all still destroy if collided with though, even when “hasPackage” is true.

Edit: I just realized I can also destroy a “Customer” by colliding with it whether or not “hasPackage” is true, even though it is only coded to do so when “hasPackage” is true. So the issue seems to be with the whole “hasPackage” thing. Only destroy on false for the package, only destroy on true for the customer, but both get destroyed regardless, while the rules of not printing to console are still followed for each object.

The OnTriggerEnter2D method could be called multiple times per frame.

If other.tag == "Package" && !hasPackage gets evaluated to true, other.tag == "Customer" && hasPackage could be true if the car collides with a “Package” and a “Customer” within the same frame.

At the top of the OnTriggerEnter2D method, log both the value of hasPackage and the other.tag into your console. This way you’ll know the values when this method gets called. And then you’ll be able to see if the values are the expected ones. The if-statements are probably working correctly.

Debug.Log("Your message " + other.gameObject.name, other.gameObject); might help. Maybe one of your scripts is attached to the wrong game object. The name might help you identify the problem faster. The other.gameObject behind the comma allows you to click the message and to see the concerning game object highlighted in the Hierarchy if the object has not been destroyed (yet).

This is not right. The script above is written for the player. This should not be on any package or customer. If it’s on each package and each customer, the hasPackage gets set for the package/customer and then you destroy the object. No more hasPackage.

However, there is no code in here that let’s the object be destroyed if the script is on the package/customer because in that case other will be the player and the tag will not be “Customer” or “Package”. Do you have this script on the player, too? Is there any code in here that you didn’t share?

Also, there’s a issue here

As per the instruction in the course so far, there’s only one script, the “Delivery” script, that is applied to the player, the package, and the customer. At this point in the course there hasn’t been any instruction to write separate code for each object, it’s just compiled together in the “Delivery” script, As for the execution error in my code, thank you for pointing that out. I actually found and fixed it myself while adding extra “if” in, but thank you for the explanation of the issue it could cause. I’m still extremely new to all of this.

OK, Not a problem. To be honest, I suppose this script can actually be on all the objects.

Your new code has some ‘issues’ that I believe is causing your new confusion: When you hit a package, if (other.tag == "Package" && !hasPackage) will run because you hit a package and don’t have a package. So, you set hasPackage to true. Now, the next if (other.tag == "Package" && hasPackage) also runs, because you hit a package and hasPackage is true (you just set it to true). So, even if you hit 1 package and the trigger only fires once, you will see both messages in the console. The trigger doesn’t fire again when you exit. For that we have OnTriggerExit2D. You should change the second ‘if’ to else if instead. Then it will only be evaluated if the first ‘if’ is not true.

if (other.tag == "Package" && !hasPackage) 
{
     Debug.Log("Hope that wasn't fragile...");
     hasPackage = true;
     Destroy(other.gameObject, destroyDelay);
     spriteRenderer.color = hasPackageColor;
}
else if (other.tag == "Package" && hasPackage)
{
     Debug.Log("I ain't got room for two of these friggin things!");
}

Turns out, that pesky little misplaced bracket was the culprit the entire time! I fixed it while adding a couple extra “if” statements, then when I saw you point it out afterwards, I tried removing the new “if” statements with the fixed bracket, and everything works again! Thank you for the help!

the “else if” thing is good to know for the future, thank you! I removed the extra “if” statements in this instance and got it working but I’m sure I’m gonna need plenty of “Else ifs” in the future!

No problem! Glad you sorted it out. I’m a little confused how that bracket could have caused the issue, though. The only thing it would have done is set the sprite’s color to always be noPackageColor so it would always look like you don’t have a package even when you do.

Same here, I definitely don’t see the link between the bracket and the destroy command, but It’s just a good learning experience regarding how temperamental code can be and what kind of little errors I need to keep a sharp eye out for in the future!

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms