1
\$\begingroup\$

So right now I have enemies that spawn behind objects with a delay.

What I need is to display an image on the screen 5 seconds after each enemy spawns (it's to show the player it has been "attacked") and that image has to disappear after like 2 seconds so.

I know I have to use WaitForSeconds but I don't know how because everything I've tried isn't working.

Here's my code:

 public class TimedSpawn : MonoBehaviour {

     public GameObject spawnee;
     public bool stopSpawning;
     public float spawnTime;
     public float spawnDelay;

     // Use this for initialization
     void Start () {
         InvokeRepeating ("SpawnObject", spawnTime, spawnDelay);
     }

     public void SpawnObject (){
         Instantiate (spawnee, transform.position, transform.rotation);

         if (stopSpawning) {
             CancelInvoke ("SpawnObject");
         }
     }
 }
\$\endgroup\$
1
\$\begingroup\$

Use a co routine to accomplish this. I don't know how you want to display the image, but for this example I will use the Unity UI Image. Example below:

public class Example : MonoBehaviour {

public GameObject spawnee;
public bool stopSpawning;
public Image image;

public float spawnTime;
public float spawnDelay;

// Use this for initialization
void Start()
{
    image.gameObject.SetActive(false);
    InvokeRepeating("SpawnObject", spawnTime, spawnDelay);
}

public void SpawnObject()
{
    Instantiate(spawnee, transform.position, transform.rotation);
    StartCoroutine(DisplayMessage(5, 2, image));

    if (stopSpawning)
    {
        CancelInvoke("SpawnObject");
    }
}

public IEnumerator DisplayMessage(float displayOffset, float displayDuration, Image im)
{
    float time = 0f;
    do
    {
        time += Time.deltaTime;
        yield return null;
    }
    while (time < displayOffset);

    im.gameObject.SetActive(true);

    float time2 = 0f;
    do
    {
        time2 += Time.deltaTime;
        yield return null;
    }
    while (time2 < displayDuration);
    im.gameObject.SetActive(false);
}
}

Hope this helps.

\$\endgroup\$
1
\$\begingroup\$

Well, all those co-routines and waiting for some seconds are nice but, why not just use Invoke() for this purpose as well?

//...
public void SpawnObject (){
    var warningDelay = 5.0;
    Instantiate (spawnee, transform.position, transform.rotation);
    Invoke("CreateWarningImage", warningDelay);
    if (stopSpawning) {
        CancelInvoke ("SpawnObject");
    }

}
//someTransform is where you want the image to be, assuming you've already defined it
public void CreateWarningImage(){
    Instantiate (warning, someTransform.position, someTransform.rotation);
}

And then, you just put a destroy on the a script's Awake() function which is on the image like so:

var lifetime = 2.0;
function Awake()
{
    Destroy(gameObject, lifetime);
}

Note that I'm assuming you're not spawning hundred thousand enemies per second, so the performance difference between an invoke call (looks for a string) and a co-routine shouldn't matter at all. For the simplest stuff (like doing one thing after some seconds), you shouldn't really need anything other than Invoke().

\$\endgroup\$
  • \$\begingroup\$ You shouldn’t need a separate script for the delayed Destroy call. Simply calling Destroy on the GameObject returned by Instantiate immediately after it’s instantiated inside of CreateWarningMessage should be sufficient. \$\endgroup\$ – Ed Marty Nov 6 '17 at 13:37
  • \$\begingroup\$ @EdMarty Ah yes, that's correct. Though he might want different images to stay at different intervals on screen and just instantiating them and leaving them to do their own thing could be better. (Highly dependent on the project etc.) \$\endgroup\$ – John Hamilton Nov 6 '17 at 14:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.