• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by El-Deiablo · May 28, 2016 at 05:04 AM · triggercoroutinedestroygameobject

Problem Destroying Gameobject

I recently figured out how to get my slow motion powerup working, but now I am having trouble destroying the object if it is not triggered. I can destroy by setting the destroy time a few seconds higher than the coroutine time, but that leaves the powerup on screen for too long. I tried creating a bool and setting it equal to false. This is not working. The object won't destroy and my coroutine won't finish even if a trigger occurs (without the bool or update method the coroutine finishes fine). I may have it set up wrong. I want the powerup to stay on screen for 3-5 seconds so the player must be quick to pick it up. I would really appreciate some help.

Heres my code:

 using UnityEngine;
 using System.Collections;
 
 public class TimeChangingPowerUp : MonoBehaviour {
 
     public AudioClip powerUpSound;
     public float time;
     public float speed;
     private bool Active=false;
     //private bool playerEntered;
 
     /*public void ActivatePowerUpSlowMotion(float time, float speed)
     {
         StartCoroutine (SlowMoRoutine (time, speed));
     }*/
 
     void Update(){
 
         if (Active) {
             
             Destroy (gameObject, 3);
 
         }
         
     }
 
     IEnumerator SlowMoRoutine(float time, float speed)
     {
         Active = true;
         //time = Time.unscaledTime;
         //Destroy(gameObject );
         float duration = time * speed;
         Time.timeScale = speed;
         yield return new WaitForSeconds (duration);
         Time.timeScale = 1f;
         Destroy (gameObject);
 
     }
 
     void OnTriggerEnter2D(Collider2D other){
 
         if (other.tag == "Player") {
             
             Active = true;
             GameObject sound = new GameObject ();
             sound.transform.position = transform.position;
             AudioSource audioSource = sound.AddComponent<AudioSource> ();
             audioSource.clip = powerUpSound;
             audioSource.Play ();
             Destroy (sound, powerUpSound.length);
             gameObject.GetComponent <SpriteRenderer > ().enabled = false;
             StartCoroutine (SlowMoRoutine (time, speed));
 
         } 
          
     }
 
 }
Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image cjdev · May 28, 2016 at 04:05 PM 0
Share

You know that you're calling Destroy() twice on your gameObject right? One of them won't be able to destroy it. You might also run into the fact that the Destroy function doesn't actually take effect until the end of the "cycle", after updates and all coroutines are finished.

avatar image El-Deiablo · May 28, 2016 at 04:59 PM 0
Share

@cjdev

I understand what you are saying, but the way I want my powerup system to work is:

1) Power Spawns 2) If Player triggers powerup, coroutine starts, and gameobject is destroyed after cprputine finishes. 3) If Player does not trigger powerup the powerup is destroyed after 5 secs.

I don't want an unused powerup on the screen for a long period of time.

3 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by yackson-cc · May 28, 2016 at 06:46 PM

Hi!

you hav the error in this sentence

 void update()
 {
     Destroy(gameObject, 3);
 }

you must remember that this function work one time for frame, so it's in a blucle, and always set the same seconds for destroy = 3, destroy = 3, destroy = 3, destroy = 3, destroy = 3, xD you must call this function only one time.

understand me?

sorry for my english! I am from colombia.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by Bunny83 · May 30, 2016 at 05:09 PM

You have a conceptional problem here. When calling Destroy with a delay that call is final. Once invoked you can't abort that call. It should only be used when you want to specify a max life time for the object.

So in your case you shouldn't call Destroy unconditionally. There are usually two ways how to approach this problem:

  • Seperate the powerup pickup logic from the actual powerup effect. So two seperate scripts / objects. The powerup pickup script can be the same for all powerups. This object has the trigger collider and all it does is creating the referenced "powerup prefab" and parent it to the player. The pickup script can have it's own max lifetime seperate from the actual powerup.

  • The second way is to keep everything in one script / component as you have it now, but include the pickup timeout in the coroutine.

For the first solution you would do something like this:

 public class PickUp : MonoBehaviour
 {
     public GameObject powerUp;
     public float lifeTime = 3f;
     void Start()
     {
         Destroy(gameObject, lifeTime);
     }
     void OnTriggerEnter2D(Collider2D other)
     {
         if (other.tag == "Player") {
             GameObject obj = (GameObject)Instantiate(powerUp);
             obj.transform.parent = other.transform;
         }
     }
 }

Your "TimeChangingPowerUp" would be attached to the prefab that you reference in your PickUp script. Inside your "TimeChangingPowerUp" you would simply start the coroutine inside Start when it's attached to the player. Of course the Update method isn't necessary anymore.

The second solution would be something like that:

 public float lifeTime = 3f;

 void Start()
 {
     StartCoroutine(SlowMoRoutine( time, speed));
 }
 
 IEnumerator SlowMoRoutine(float time, float speed)
 {
     float timeOut = Time.time + lifeTime;
     while(!Active && Time.time < timeOut)
         yield return null;
     if (!Active){
         Destroy(gameObject);
         yield break;
     }
      float duration = time * speed;
      Time.timeScale = speed;
      yield return new WaitForSeconds (duration);
      Time.timeScale = 1f;
      Destroy (gameObject);
  }
  void OnTriggerEnter2D(Collider2D other)
 {
      if (other.tag == "Player")
      {
          Active = true;
          GameObject sound = new GameObject ();
          sound.transform.position = transform.position;
          AudioSource audioSource = sound.AddComponent<AudioSource> ();
          audioSource.clip = powerUpSound;
          audioSource.Play ();
          Destroy (sound, powerUpSound.length);
          gameObject.GetComponent <SpriteRenderer > ().enabled = false;
      } 
  }


Instead of creating that temp GO for the audiosource you might want to use AudioSource.PlayOneShot. That method will create an internal temp GameObject which is destroyed automatically once the clip is finished.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

Answer by El-Deiablo · May 30, 2016 at 05:30 PM

I figured it out! I added another coroutine that disables the spriterender after 3 seconds and then the object destroys after 17. Powerup still works like normal if triggered.

Here's the end result:

 using UnityEngine;
 using System.Collections;
 
 public class TimeChangingPowerUp : MonoBehaviour {
 
     public GameObject particle;
     public AudioClip powerUpSound;
     public float time;
     public float speed;
     bool Active=false;
     //private bool playerEntered;
 
     /*public void ActivatePowerUpSlowMotion(float time, float speed)
     {
         StartCoroutine (SlowMoRoutine (time, speed));
     }
 
     void Start(){
         Active =false;
     }*/
 
     void Update(){
 
         if (Active==false) {
             StartCoroutine (DestroyGameObject());
         }
         
     }
 
 /*void OnDisable(){
     StartCoroutine (SlowMoRoutine (time, speed));
 
     }*/
 
     IEnumerator SlowMoRoutine(float time, float speed)
     {
         Active = true;
         //time = Time.unscaledTime;
         //Destroy(gameObject );
     //float duration = time / speed;
         float duration = time * speed;
         Time.timeScale = speed;
         yield return new WaitForSeconds (duration);
         Time.timeScale = 1f;
         Destroy (gameObject);
 
     }
 
     IEnumerator DestroyGameObject(){
 
         yield return new WaitForSeconds (3);
         gameObject.GetComponent <SpriteRenderer > ().enabled = false;
         yield return new WaitForSeconds (17);
         Destroy (gameObject);
 
     }
         
 
     void OnTriggerEnter2D(Collider2D other){
 
         if (other.tag == "Player") {
             
             Active = true;
             GameObject clonedParticle;
             clonedParticle =Instantiate (particle, transform.position, transform.rotation) as GameObject ;
             GameObject sound = new GameObject ();
             sound.transform.position = transform.position;
             AudioSource audioSource = sound.AddComponent<AudioSource> ();
             audioSource.clip = powerUpSound;
             audioSource.Play ();
             Destroy (clonedParticle, 1.2f);
             Destroy (sound, powerUpSound.length);
             gameObject.GetComponent <SpriteRenderer > ().enabled = false;
         StartCoroutine (SlowMoRoutine (time, speed));
             //Destroy (gameObject);
 
 
         } 
          
     }
 
 }

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

6 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Destroy Without A Collision Or Trigger 2 Answers

Pseudo code: trigger portal system with coroutines 0 Answers

How to run a coroutine if in a trigger but run a different one if outside it? 1 Answer

After building move doesnt move 1 Answer

Problem with timed code-execution (audioplay and object destruction) 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges