- 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