Adding a delay to this raycast script [SOLVED]

Hi,

I’m trying to add a delay to the below script using yield.
I’ve tried inserting it after the update, but didn’t seem to work.
Can I get some pointers?

 yield WaitForSeconds(2);
#pragma strict

var deadReplacementPosition : Vector3;
var deadReplacementRotation : Quaternion;
var Block:GameObject;
var Block2:GameObject;
var squareSize : float = 0f;
var hit : RaycastHit;
var dieSound : AudioClip;
var initialDelay = 1.0;
var fadeSpeed = 1.0;
var explosion : Transform;
var damagesound : AudioClip;
var myTransform : Transform;




function Awake() {
   myTransform = transform; // this objects transform
}




var object : Transform;


    function Update () {
       

        if (Input.GetMouseButtonDown (0)) {
           
      //  if (Input.GetButtonDown ("Fire1")) {
            // Construct a ray from the current mouse coordinates
            var hit : RaycastHit;
            var distance : float = 100;
            var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
            if (Physics.Raycast (ray, hit , distance)) {
                if (hit.collider.tag == "FlowerTrigger")
                            
                {
                   
                  

            

        var mousePos : Vector3 = Input.mousePosition;
               mousePos.z = 10; //I'm not sure why you're setting this to such a specific value?
         var objectPos : Vector3 = Camera.main.ScreenToWorldPoint(mousePos);
         //now you've gotten objectPos' initial value,
         //lock it to a nearby grid point
         objectPos.x = Mathf.Round(objectPos.x/squareSize) * squareSize;
         objectPos.y = Mathf.Round(objectPos.y/squareSize) * squareSize;
         objectPos.z = Mathf.Round(objectPos.z/squareSize) * squareSize;
   
            
         Instantiate(Block, objectPos, Quaternion.identity);
         Instantiate(Block2, objectPos, Quaternion.identity);
               

 
Destroy(this.gameObject);       
     }
            }

  }}

Take a look at this video to get a handle on coroutines:

The code samples are in C#, but there are other tutorials for Js, which is the language you’re using.

Thanks, Kurt, good tutorial.
I’ve used iEnumerator and coroutines before, but not with JS.
I’ve cobbled together the following, but not working.
Any suggestions?

#pragma strict

var deadReplacementPosition : Vector3;
var deadReplacementRotation : Quaternion;
var Block:GameObject;
var Block2:GameObject;
var squareSize : float = 0f;
var hit : RaycastHit;
var dieSound : AudioClip;
var initialDelay = 1.0;
var fadeSpeed = 1.0;
var explosion : Transform;
var damagesound : AudioClip;
var myTransform : Transform;


function Awake() {
   
myTransform = transform;
}
var object : Transform;
function Update () {
       

if (Input.GetMouseButtonDown (0)) {
var hit : RaycastHit;
var distance : float = 100;
var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, hit , distance)) {
if (hit.collider.tag == "FlowerTrigger")
                          
{
                   
       yield;
    }
   
    print("delay");
   
yield WaitForSeconds(3f);  


 

var mousePos : Vector3 = Input.mousePosition;
mousePos.z = 10;
var objectPos : Vector3 = Camera.main.ScreenToWorldPoint(mousePos);
         //now you've gotten objectPos' initial value,
         //lock it to a nearby grid point
objectPos.x = Mathf.Round(objectPos.x/squareSize) * squareSize;
objectPos.y = Mathf.Round(objectPos.y/squareSize) * squareSize;
objectPos.z = Mathf.Round(objectPos.z/squareSize) * squareSize;
   
   
Instantiate(Block, objectPos, Quaternion.identity);
Instantiate(Block2, objectPos, Quaternion.identity);
        
 
}
   
Destroy(this.gameObject);       
    
}}

If yield can’t be used in an update, how do I write this as a coroutine?

At the moment in code where you want something to occur, you make a call:

StartCoutine( MyCoroutine());

Inside that coroutine you make a wait of the appropriate amount of time, then do whatever it is you want done as a delay.

Here is a simple utility example that uses a lambda/functor to enclose the desired action you want to do in the future. That way you can use the same PerformActionAfterTime() function over and over again for as many different “actions” as you want.

A functor is simply an anonymous snippet of code (potentially with some arguments) that you want executed by someone else somewhere else, and passing it in as a System.Action is essentially supplying a “pointer” to it.

using UnityEngine;
using System.Collections;

// This is an example of simple coroutine use to do an
// arbitrary action at a delayed point in time.
// To test, put it on a gameObject and run and press Space.
// See debug output log for output.
// You can fire off as many of these as you want at a time.

public class myscript : MonoBehaviour
{
    IEnumerator PerformActionAfterTime( float delayAmount, System.Action action)
    {
        yield return new WaitForSeconds (delayAmount);
        action ();
    }

    void Update ()
    {
        if (Input.GetKeyDown( KeyCode.Space))
        {
            Debug.Log ( "Space was pressed...");
            StartCoroutine( PerformActionAfterTime ( 2.0f,
            () => {
                    Debug.Log ( "Delayed printing!");
                 }
            ));
        }
    }
}

Ok, thanks Kurt.
I tried implementing this into my script, but won’t work.
I’m confused about how to call this “WaitForIt” coroutine in this code:

#pragma strict

var deadReplacementPosition : Vector3;
var deadReplacementRotation : Quaternion;
var Block:GameObject;
var Block2:GameObject;
var squareSize : float = 0f;
var hit : RaycastHit;
var dieSound : AudioClip;
var initialDelay = 1.0;
var fadeSpeed = 1.0;
var explosion : Transform;
var damagesound : AudioClip;
var myTransform : Transform;

function Awake() {
  
myTransform = transform;
}
var object : Transform;
function Update () {
 
  
StartCoroutine("WaitForIt");


if (Input.GetMouseButtonDown (0)) {
var hit : RaycastHit;
var distance : float = 100;
var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, hit , distance)) {
if (hit.collider.tag == "FlowerTrigger")                  
{
var mousePos : Vector3 = Input.mousePosition;
mousePos.z = 10;
var objectPos : Vector3 = Camera.main.ScreenToWorldPoint(mousePos);
         //now you've gotten objectPos' initial value,
         //lock it to a nearby grid point
objectPos.x = Mathf.Round(objectPos.x/squareSize) * squareSize;
objectPos.y = Mathf.Round(objectPos.y/squareSize) * squareSize;
objectPos.z = Mathf.Round(objectPos.z/squareSize) * squareSize;
  
function WaitForIt(){
yield WaitForSeconds(1);
}  
  
  
Instantiate(Block, objectPos, Quaternion.identity);
Instantiate(Block2, objectPos, Quaternion.identity);
       
}

Destroy(this.gameObject);      
  
}}}

Your function WaitForIt() waits for 1 second and then does nothing. Put what you want to do at the END of that function.

Thanks, Kurt!
Slowly but surely I’m starting to understand…

Here’s my working code:

#pragma strict

var deadReplacementPosition : Vector3;
var deadReplacementRotation : Quaternion;
var Block:GameObject;
var Block2:GameObject;
var squareSize : float = 0f;
var hit : RaycastHit;
var dieSound : AudioClip;
var initialDelay = 1.0;
var fadeSpeed = 1.0;
var explosion : Transform;
var damagesound : AudioClip;
var myTransform : Transform;
var timer : float = 2;

function Awake() {
   
myTransform = transform;
}
var object : Transform;
function Update () {
   
   


       

if (Input.GetMouseButtonDown (0)) {
var hit : RaycastHit;
var distance : float = 100;
var ray : Ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray, hit , distance)) {
if (hit.collider.tag == "FlowerTrigger")
                          
{
       
       
   
 



StartCoroutine("WaitForIt"); 

}}}}

function WaitForIt(){
yield WaitForSeconds(.2);





var mousePos : Vector3 = Input.mousePosition;
mousePos.z = 10;
var objectPos : Vector3 = Camera.main.ScreenToWorldPoint(mousePos);
         //now you've gotten objectPos' initial value,
         //lock it to a nearby grid point
objectPos.x = Mathf.Round(objectPos.x/squareSize) * squareSize;
objectPos.y = Mathf.Round(objectPos.y/squareSize) * squareSize;
objectPos.z = Mathf.Round(objectPos.z/squareSize) * squareSize;

//var mousePos : Vector3 = Input.mousePosition;
//mousePos.z = 10;
//var objectPos : Vector3 = Camera.main.ScreenToWorldPoint(mousePos);

Instantiate(Block, objectPos, Quaternion.identity);
Instantiate(Block2, objectPos, Quaternion.identity);
        
Destroy(this.gameObject); 
  

}

Here’s another insight about coroutines: any function that returns an IEnumerator is also called a “generator.”

Whereas a traditional function does some stuff and returns (maybe returning some value), a generator can return any number of things via the IEnumerator that it creates when you first call it.

The way Unity uses that mechanism is that you create an IEnumerator object when you call PerformActionAfterTime(), and then you immediately hand that IEnumerator object into Unity.

Unity records that object inside the specific gameObject instance that you are in, then every single frame it asks that IEnumerator “Give me another thing.” Based on what that IEnumerator returns (like a “WaitForSeconds()” or null or whatever), Unity either calls it again the very next frame, or else waits the specified amount of time before asking for another thing.

From the standpoint of your code inside the IEnumerator generator, it is essentially “paused” until Unity decides to call it again and wake it up, when it picks up where it left off and moves forwards.