1
\$\begingroup\$

I want to make a bomb-like game object, that when instantiated, takes 2 seconds to charge, and then some other event triggers. The problem is I can't make it scale smoothly for 2 seconds, and then trigger some other event.

Here's what I have:

public GameObject bombGO;

// This method is inside a Input.GetButtonDown("Fire2") event in Update()
void ChargeBomb() {
    Vector3 offset = transform.rotation * playerOffset;
    GameObject bomb = (GameObject) Instantiate(bombGO, transform.position + offset, transform.rotation);
    bomb.transform.localScale += new Vector3(0.2f, 0.2f, 0.2f);
    // Now I want this transform to be fired continuosly for 2 seconds, while the object progressivelly and smoothly gets larger, up to 1.0f scale
    // after 2 seconds, destroy the said object
}

How can I do it?

\$\endgroup\$

3 Answers 3

0
\$\begingroup\$

manage all in the Update (I use c# and pseudo code)

    bool Charging=false;
    float timer = 2f; 
GameObject bomb;

    void Update() {
    ...
    if (Input.GetButtonDown("Fire2") && Charging==false ){
       bomb = (GameObject) Instantiate(bombGO, transform.position + offset,transform.rotation);
        Charging=true;
    }
    ...
    if Charging {    
     if (timer > 0 )
     {
     Vector3 offset = transform.rotation * playerOffset;
        bomb.transform.localScale += new Vector3(0.2f, 0.2f, 0.2f);
        // Now I want this transform to be fired continuosly for 2 seconds, while the object progressivelly and smoothly gets larger, up to 1.0f scale    
       //Update timer 
       timer = timer - Time.deltaTime;
     } else {
        // after 2 seconds, destroy the said object 
        // ...add destroy object logic

        //reset timer and flag
        Charging=false;  //maybe it's useless if you destroy the object
        timer = 2f;     //maybe it's useless if you destroy the object
     }
    }
    ...
    }
\$\endgroup\$
6
  • \$\begingroup\$ sorry I meant that the Charge code is in Input.GetButtonDown("Fire2") event, which is fired only once per key press, I edited my question \$\endgroup\$
    – Borislav
    Jul 3, 2015 at 7:02
  • \$\begingroup\$ I edited the response. \$\endgroup\$ Jul 3, 2015 at 7:09
  • \$\begingroup\$ no, this doesnt work. I don't need to instantiate the object every time, just once, and then only change its scale gradually \$\endgroup\$
    – Borislav
    Jul 3, 2015 at 7:17
  • \$\begingroup\$ if Charging { grants you only one istantiation \$\endgroup\$ Jul 3, 2015 at 7:22
  • \$\begingroup\$ no, your code has the Instantiate where the localScale is too \$\endgroup\$
    – Borislav
    Jul 3, 2015 at 7:32
1
\$\begingroup\$

I have to agree with Ben. You can do things in Update but once you start having to manage many different objects changing simultaneously it is much nicer to do it with CoRoutines.

Having said that, it took me several iterations and seeing good examples in the Unity demos to feel like I understood them properly. For now, go with what makes the most sense. But set aside some time to experiment with coroutines.

\$\endgroup\$
0
\$\begingroup\$

Coroutines are very useful for actions like these. When programming a game you've probably found yourself wishing each object was independent with the ability to do things over time without blocking other objects from executing. To achieve this normally, we'd need a new thread for each object that exists in the game world ( which is is impractical for several reasons. )

Coroutines allow us to program objects as if they run on a separate thread ( but they don't. ) Using "yeild return" we can tell Unity to continue the execution of this method later.

My implementation:

private IEnumerator ChargeBomb( GameObject bomb )
{
    // Percentage of the scale we have completed.
    var t      = 0.0f;

    // The scale we're going from and the scale we're going to.
    var start   = new Vector3( 0.2f, 0.2f, 0.2f );
    var end     = Vector3.one;

    // In other words while our scale is not equal to our "end" vector.
    while( t < 1.0f )
    {
        // Scale the bomb. 2.0 here because you specified the scale to be over 2 seconds.
        t += ( Time.deltaTime / 2.0f );
        bomb.transform.localScale = Vector3.Lerp( start, end, t );

        // Wait till the next frame.
        yield return null;
    }

    // Bomb is scaled, invoke an event here.
}

We start out defining what scales we'd like to lerp between, then enter a loop. Here we scale using Vector3.Lerp and we increase the lerp fraction by the delta time / 2 ( so this takes place over two seconds. ) We use yield return null to tell Unity to come back next frame so the rest of the game isn't blocked. Do this until the object is fully scaled.

I find this much nicer and easier to understand than managing a bunch of state in the update method.

http://docs.unity3d.com/Manual/Coroutines.html http://docs.unity3d.com/ScriptReference/Vector3.Lerp.html

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .