Shrinking Object

Alright, I know this sounds difficult, but here it is.

I wish to have the ability to ‘Shrink’ certain objects. I would like to launch a green projectile at an object and when the projectile hits the object, the object shrinks down to about 1/20th it’s previous size. As a reference, look at the Shrink Ray from Duke Nukem: Forever. Something like that.

However, I have no clue how to go about this. Hints please? :slight_smile: :sunglasses:

When the projectile hits the object, modify Transform.localScale

or use Transform.root.localScale to be sure you scale down the entire instance and not just from the collider’s owner and its children.

There are several patterns you can use to actually notify or change the hit instance. If the object can grow back to full size after a set amount of time, the best bet is probably to send some sort of OnHit message and let the object which was hit handle itself. In other words, keep it generic on the projectile side, so all it has to do is hit something and tell it its been hit. (If you do this, you will probably want to send the message to the collider.root.) Then…

On the hit object (in the “OnHit” function triggered by the hit) start a co-routine which will shrink itself, wait for X seconds, then grow back up. You can also use a co-routine with a LERP to do the actual shrink and grow animation (if you don’t have FCurve-driven animation to trigger).

If you know that the collider’s root object will definitely have the function, you could do a hit.collider.root.GetComponent<>() to get the script component with the function, then call it directly. This might be better performance-wise but you may not even notice the difference and SendMessage(“OnHit”), with the option to not require a receiver, is definitely the easiest and will allow the projectile to hit anything and only objects which can shrink will have a reaction to the sent event trigger (it is optional so other hit objects would just ignore the hit, or have some other reaction, etc.).

Also, just to add, if you want the object to actually shrink down in size use something like:

var Shrink : boolean = false;
 
If (Shrink == true  Transform.localScale != Vector3(x,y,z)) // set x,y,z to the size you want it to shrink to
{
Transform.localScale -= Vector3(0.1,0.1,0.1);
}

put this code in an Update so it will shrink by 0.1 every cycle. But not the var Shrink part.

Wraith - good start but NEVER use an equality comparison between floats! Esp. in a situations like this.

Instead:

var Shrink : boolean = false;
var smallScale = Vector3(0.1,0.1,0.1);
 
if (Shrink == true)
{
    if (Transform.localScale > smallScale)
    {
        Transform.localScale -= Vector3(0.1, 0.1, 0.1); //Consider using a lerp or something
    }
    else
    {
        Transform.localScale = smallScale;
        Shrink = false;
    }
}

The code will need to be in an update etc. the variables should be class level (so you don’t keep setting Shrink to false every update).

I would not recommend using Update() for this. Updates should only be used if necessary and this is much better as a co-routine. You also don’t need the bool check if the co-routine is handling timing. If there is no timing, then you will need the bool, but only to track the state and trigger the appropriate co-routine when the time comes. Then in the co-routine, you will end up using a while loop, which is where you want the check to see if it is time to stop doing work (depending on the logic you need).

You also might have prettier results using an interpolation function. They are all over the internet. Unity has the linear one (Lerp) built in, which is the best place to start until you have time in your development schedule for fine-tuning:

Also, if you use Time.fixedTime instead in that example, it will scale with the game speed (in case you are using Time.timeScale to control pausing your game.)

Hey, You also should not use a -= or any minus on a scale vector, You could end up with zero scale which will cause issues or a negative scale. Use *= instead, so if you want to scale something half you would do transform.localScale *= 0.5f; or if you wanted to scale just the y part of it you’d use transform.localScale = Vector3.Scale( transform.localScale, new Vector3(1, 0.5f, 1) )

Thanks for all the help guys! I’ll be getting to work now…sigh :slight_smile:

iTween also has a ScaleTo method.