Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Destroy projectile upon collision with target

Discussion in 'Scripting' started by KairosKinema, Feb 16, 2009.

  1. KairosKinema

    KairosKinema

    Joined:
    Jan 24, 2007
    Posts:
    36
    I have read through documentation on using "Destroy" and collisions and whatnot and other threads about this but nothing seems to be working, so I'll lay it out for any soul brave enough (or kind enough) to offer a response:

    I'm shooting a projectile at a moving target (a cube). When the projectile collides with the cube, I want the projectile to destroy itself (among other things but thats another story).

    I've tried attaching a script to the prefab projectile that says:

    function OnTriggerEnter (other : Collider) {
    Destroy (this);
    }

    or I've tried the following, understanding it to mean that the "Destroy" command will apply to the game object the script is attached to:

    function OnTriggerEnter (other : Collider) {
    Destroy (gameObject);
    }

    No luck there either. So I tried exposing a game object variable, dragging the projectile prefab onto it in the Inspector to make sure the script knew what object I would be destroying upon collision, like so:

    var projectile : GameObject;

    function OnTriggerEnter (other : Collider) {
    Destroy (projectile);
    }

    I'm simply having no luck with this. Do I need to be attaching this destroy script to the target being hit and not the projectile hitting the target in order to destroy the projectile?

    I'm lost. I've tried fiddling and coding and researching and reading for over two hours and I've found myself contemplating pointing the business end of my S&W .45 1911 towards the area of my forehead between my eyes....

    Any help? Thanks a ton in advance!!!
     
  2. Tempest

    Tempest

    Joined:
    Dec 10, 2008
    Posts:
    1,286
    The projectile has a box collider, and that box collider has "Is Trigger" checked?
     
  3. KairosKinema

    KairosKinema

    Joined:
    Jan 24, 2007
    Posts:
    36
    Yes.

    I've tried it with the "Is Trigger" checked and unchecked.

    I've included a bit of code like this too:

    function Start ( ) {

    collider.isTrigger = true;
    }

    Just in case the "Is Trigger" box was unchecked. Still no dice.

    My understanding is that I only need the projectile to have a box collider and a rigidbody in order to respond to physics, while the target which needs no gravity or drag or whatnot only needs to have a box collider attached to it, right?
     
  4. GargerathSunman

    GargerathSunman

    Joined:
    May 1, 2008
    Posts:
    1,571
    The correct answer is to make the projectile have isTrigger NOT checked and use function OnCollisionEnter(hit : Collision).

    This is for the bullet.

    Code (csharp):
    1. function OnCollisionEnter(hit : Collision)
    2. {
    3.    Destroy(gameObject);
    4. }
    isTrigger is meant to be used when you want an effect to occur without causing any physics calculations.

    If you want physics to work on an object, it needs a rigidbody attached.

    If both objects have a non-mesh collider and one has a rigidbody, you should have the projectile die if it has the above script.
     
    lexxxalmeida likes this.
  5. KairosKinema

    KairosKinema

    Joined:
    Jan 24, 2007
    Posts:
    36
    Thanks GS, you were right.

    I wondered about using OnTriggerEnter instead of OnCollisionEnter, and it seems your solution works great.

    Now my question is how do I differentiate between collision types? For example, when the projectile hits the ground, its a collision so the projectile destroys itself (good).

    However, when the projectile hits the target and destroys itself I would love for a score counter to be incremented according to the point value of the target hit.

    This gets into inter-script communication which has been a singularly perplexing obstacle for me as well.

    Each time I try to declare a variable in one script and point it to another script on another game object to execute a function there or pass a value along or what have you, I am unable to do so.

    In this case, it seems all I want is for there to be a script attached to each target that says, in pseudocode:

    If I am hit by a projectile, then

    add some points to the totalScore variable that is attached to some other game object.


    I've read the documentation on how to access other components--including scripts--from other objects and scripts, but it doesn't seem to work for me.

    It's quite frustrating as I can see that inter-script communication and operations will be critical to any project involving more than one object or script.

    I'd really appreciate it if someone would show me how to do the following:

    1. Empty game object has script named "Score" that keeps total score with a variable called totalScore

    2. Target object has a script named "hit" that detects when a projectile has collided with the target and then tells the script "Score" on the empty game object to increment its variable totalScore by one

    This seems like it should be ridiculously easy, but my experience has been anything but easy (though it has been pretty ridiculous!).

    Thanks again all. I appreciate all the cool, helpful people out there who've been throwing me a life-preserver.
     
  6. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Code (csharp):
    1.  
    2.  
    3. private var scoreScript : ScoreScript;
    4.  
    5. function Start() {
    6. var scoreObject : GameObject;
    7. scoreObject = GameObject.FindWithTag ("ScoreManager");
    8. scoreScript = scoreObject.GetComponent(ScoreScript);
    9. }
    10.  
    11. function OnCollisionEnter(hit : Collision)
    12. {
    13.    scoreScript.Score += 1;
    14.    Destroy(gameObject);
    15. }
    This of course assumes that your empty GO has a tag of "ScoreManager" assigned and the script is named "ScoreScript"

    Perhaps it would be a better approach for you to tell us what difficulty you have run into trying to use the material in the docs. Is there a fundamental concept you're having difficulty with? I'm sure we could help with that.
     
  7. KairosKinema

    KairosKinema

    Joined:
    Jan 24, 2007
    Posts:
    36
    Queitus, your example code worked great. I only changed one thing, in that I didn't use the GameObject.FindWithTag command but rather the GameObject.Find command (I'm not very proficient with tags and adding new ones, etc... though if they're helpful I'm sure I'll learn about them in the future).

    Whlie your example works, I'd certainly like to better understand how so that I needn't pester the forums with similar questions in the future, or better yet, so that I can help someone else out who has the same problem I did.

    First, I assume that you declared the first variable in your example code as private because there's no need to edit it directly through the Inspector? I'm unsure why its preferable to use a private variable in this situation.

    Second, much of my confusion likely stems from the issue of capitalization. This line in your code threw me for a loop:

    private var scoreScript : ScoreScript;

    I thought that whatever you entered after a colon had to be a valid variable Type (int, bool, float, GameObject, Camera, etc.). I do not understand the significance of declaring a variable as a Type that is its own name with the first letter capitalized (i.e. scoreScript vs. ScoreScript). What is going on there if you don't mind me asking?

    I'm thrilled because when I plugged your sample code into my project it worked great. I did delete the line with the destroy command and attached the script to the targets and not the projectile. This is because I want each of the three targets to be worth a different number of points and I didn't need the targets to destroy themselves after being hit, only the projectile needed to be destroyed to make room for the next one that was shot.

    So I added this line of code at the top as an exposed variable:

    var tScore = 1;

    That way I can attach the script to my targets and manually change their point values (the tScore variable) in the Inspector. Then I plugged that variable into your code as follows so that when each target is hit it increments the total score by the proper amount:

    function OnCollisionEnter(hit : Collision)
    {
    scoreScript.Score += tScore;
    var currScore = scoreScript.Score;
    print(currScore);
    // Destroy(gameObject);
    }


    So far I'm making real progress in these areas and I couldn't be more excited or more grateful for all this help.

    One last question, Q:

    If I had wanted to execute a function in the ScoreScript and not just change the Score variable, and say the hypothetical function in this case was called "Thing," how would I have called that function in your sample code? Like this?

    function OnCollisionEnter(hit : Collision)
    {
    scoreScript.Thing ( );
    }


    In other words, in this line of code

    scoreScript.Thing ( );

    is the word after the period always a variable UNLESS it has parentheses after it since that would signify a function instead? If not, how would I execute a function in another script instead of just changing a variable?

    By the way, I read your recent response to another thread on accessing scripts from other scripts, as well as the two threads you provided hyperlinks to, and the documentation, but it still isn't making sense to me.

    Explaining it using this sample code you've generated for me, though, would make sense to me inasmuch as I'm using it in a project that is familiar to me and is working. I hate to ask people to repeat themselves, or to tell me something I can read for myself, but I'm stuck on this one!

    Thank you yet again!