- Home /
Problem with timed code-execution (audioplay and object destruction)
I am trying to create a game-object that increases a counter and plays a sound on being triggered and then being destroyed. Think of it like the Coins in Mario and alike.
I do have my Script for the object which at the current state, increases the counter (Clartiy) just once, plays the sound, then turns the object invisible. Planned was that a second collision destroys it without doing anything else, though that part fails and it actually plays the sound again.
     void OnTriggerEnter(Collider c) 
     {
     
         if (c.gameObject.tag == "Player" && firstCol) 
         {
             Debug.Log("firstCol=" + firstCol);
             audio.PlayOneShot(gong, 1.8f);
             Player.GetComponent<Player>().Clarity += 1;
             renderer.enabled = false;
             firstCol = false;
             Debug.Log("firstCol=" + firstCol);
         }
 
         if (c.gameObject.tag == "Player" && !firstCol)
         {
             Debug.Log("firstCol=" + firstCol);
             Debug.Log("PreDestro");
             WaitForDestro();
             // tried "Destroy(gameObject);" here too, didn't work
         }
     }
 
 
     private IEnumerator WaitForDestro() {
         yield return new WaitForSeconds(0.1f);
         Debug.Log("WaitForDestro Done");
         Destroy (gameObject);
     }
firstCol is initialized as true since the first Collision is supposed to run the first if-statement. The Delay through the coroutine is there because otherwise it seems to instantly destroy the object, giving me the "Can't play a disabled audio source" problem.
as for the firstCol Debug-log, what I get there is:
 firstCol=true
 fristCol=false
 fristCol=false
 ProDestro
from walking through it once. walking through again gives me
 fristCol=false
 ProDestro
nothing else, the "WaitforDestro Done" doesn't appear either.
I also tried to work with OnTriggerExit, but that didn't solve the problem as well. Anyone know what's wrong with my Code/Approach and if there's a better way?
Answer by Kiwasi · Jun 13, 2014 at 08:23 AM
Your problem is that firstCol is being set to true in the first if, and the second if executes immediately after the first. To solve I would suggest using an if-elseif configuration. That way the second code block will not execute if the first does.
A better way to do it would be to just use timed object destruction in the first if.
 Destroy(gameObject, 5);
 // gameObject will be destroyed in 5 seconds.
Make sure the float is longer then your sound. Also ensure you have disabled any other components of relevance on the script to prevent further collisions ect.
Edit: Further Code Sample developed in comments.
 void OnTriggerEnter(Collider c){
     if (c.gameObject.tag == "Player"){
         audio.PlayOneShot(gong, 1.8f);
         // You should consider a static reference to the player component
         Player.GetComponent<Player>().Clarity += 1; 
         render.enabled = false;
         collider.enabled = false;
         // Any other component of significance should also be disabled.
         Destroy (gameObject, 5);
     }
 }
The time destruction works so far, though it now oddly enough adds 2 to the counter ins$$anonymous$$d on the first collision of just one. Plus, the object is still active during the delay between collision and destruction, allowing further collissions that increase the counter by 1 again. To solve that I'm trying to get a mix between the timed destruction and an if-elseif or rather just if-statements:
     void OnTriggerEnter(Collider c) 
     {
     
         if (c.gameObject.tag == "Player" && firstCol)
         {
             audio.PlayOneShot(gong, 1.8f);
             Player.GetComponent<Player>().Clarity += 1;
             renderer.enabled = false;
             firstCol = false;
             Destroy(gameObject, 5f);
         }
         if (c.gameObject.tag == "Player" && !firstCol)
         {
             Debug.Log("PreDestro");
             return;
         }
     }
I don't know why, but it still keeps letting me get more and more increase on the counter... (the destruction time is that high for testing reasons, I want to make sure it only lets me get one counter-increase out of a single object, no matter if it increases by one or two.
Oddly enough, the Debug.Log entry is reached every time I walk through the object, yet it still increases the counter. If I change it to an if-elseif, the first time doesn't throw the Debug-Log entry, but every other collision does... and all increase the counter none the less.
I think you missed my point. Try this code.
 void OnTriggerEnter(Collider c){
     if (c.gameObject.tag == "Player"){
         audio.PlayOneShot(gong, 1.8f);
         // You should consider a static reference to the player component
         Player.GetComponent<Player>().Clarity += 1; 
         render.enabled = false;
         collider.enabled = false;
         // Any other component of significance should also be disabled.
         Destroy (gameObject, 5);
     }
 }
oh yeah, sorry... I kinda missed the last two lines of your answer. Anyway, that works just fine now =) thanks a lot!
That would definitly be worth an upvote if I had enough reputation to do that yet xD
All good. Since I've written it I will add the code to my answer.
Your answer
 
 
             Follow this Question
Related Questions
Collecting objects? 1 Answer
using Contains(gameObject) to find and destroy a gameObject from a list 2 Answers
How come when the player runs into the coin it won't destroy? 1 Answer
Is there anyway to make an object impenetrable? 1 Answer
Animator.Rebind() not working as expected after manually changing GameObject hierarchy 0 Answers
 koobas.hobune.stream
koobas.hobune.stream 
                       
                
                       
			     
			 
                