- Home /
Can't get 2d bomb to explode on timer
I'm trying to explode a bomb on a timer and create a force using Point Effector 2D. The bomb will explode but right when i click the play button, without any timer. The timer works for anything else tested (debug log and color change).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BombScript : MonoBehaviour
{
public GameObject explosion;
public int timeToWait;
public bool startTimer=false;
void Update()
{
if (startTimer == true)
{
StartCoroutine(explodeTimer());
}
}
public void explode()
{
Instantiate(explosion, transform.position, Quaternion.identity);
Debug.Log("test");
}
IEnumerator explodeTimer()
{
yield return new WaitForSeconds(timeToWait);
GetComponent<SpriteRenderer>().color = Color.red;
explode();
}
}
Answer by Eno-Khaon · Aug 30, 2020 at 06:28 PM
As things stand right now, you should probably improve how this is set up. Let's say the bomb has a 3-second timer and your game is running at 60 frames per second. The Coroutine would be run 180 times before the bomb actually "explodes" at all!
So you should probably reformat this in one of two ways:
1) Keep the Coroutine and make sure it only runs once:
// Call this function directly from another script
// rather than from Update() in its own
public void BeginCountdown()
{
if(!startTimer) // if(startTimer == false)
{
startTimer = true; // Set it to true so it won't
StartCoroutine(explodeTimer());
}
}
To note: Once you start the timer via Coroutine, stopping it (before the bomb blows up) would require using StopCoroutine() or destroying the GameObject.
2) Run the process in Update() alone, managing some timers yourself:
float currentTime;
void Start()
{
ResetTimer();
}
void Update()
{
if(startTimer)
{
currentTime -= Time.deltaTime;
if(currentTime <= 0f)
{
explode();
}
}
}
// Calling this lets you restart the timer as needed
// *NOT* calling it lets the timer resume where it left off instead
void ResetTimer()
{
currentTime = timeToWait;
}
I tried the second option but i'm not sure i understand it. It doesn't seem to do anything different, the bomb still explodes when i hit play and it still loops Debug.Log("test"); once the timer reaches 0, but this looping can be easily fixed in the old code, changing the startTimer to false after the Coroutine starts:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BombScript : $$anonymous$$onoBehaviour
{
public GameObject explosion;
public int timeToWait;
public bool startTimer = false;
void Update()
{
if (startTimer == true)
{
StartCoroutine(explodeTimer());
startTimer = false;
}
}
public void explode()
{
Instantiate(explosion, transform.position, Quaternion.identity);
Debug.Log("test");
}
IEnumerator explodeTimer()
{
yield return new WaitForSeconds(timeToWait);
GetComponent<SpriteRenderer>().color = Color.red;
explode();
}
}
I am more concerned about not being able to time the explosion and i can't understand what's calling explode() right from the start.
Is there more than one object in your scene with BombScript on it? Since the default value of an integer is 0, that would mean any copy of the script you don't know about would likely have been unchanged, so it would trigger immediately.
Edit: Presumably, when the bomb explodes in a finalized form, it would destroy itself in the process, which would alleviate the inherent problems with duplicated Debug.Log() text.
Answer by Artik2442 · Aug 30, 2020 at 05:35 PM
Maybe this is because startTimer is equal to false... Try maybe to add:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BombScript : MonoBehaviour
{
public GameObject explosion;
public int timeToWait;
public bool startTimer=false;
void Awake() // The thing you have to add
{
startTimer = true;
}
void Update()
{
if (startTimer == true)
{
StartCoroutine(explodeTimer());
}
}
public void explode()
{
Instantiate(explosion, transform.position, Quaternion.identity);
Debug.Log("test");
}
IEnumerator explodeTimer()
{
yield return new WaitForSeconds(timeToWait);
GetComponent<SpriteRenderer>().color = Color.red;
explode();
}
}
I assume you are instantiating the bomb, so this should work...
It is a public bool so i click it with the mouse to make it true. Also the other timed actions work. I did try your code though, and it has the same behaviour.
Your answer
Follow this Question
Related Questions
bomb effect 2 Answers
Exporting FBX via 3ds Max doesn't show 'Bomb' modifier 2 Answers
How to object pool an Explosion 2 Answers
timed bomb, explosion detection 2 Answers