0

I made a test game in unity that makes it so when I click on a button, it spawns a cylinder created from a factory class. I'm trying to make it so when I create the cylinder, its height shrinks over the next 20 seconds. Some methods I found are difficult to translate into what I'm doing. If you could lead me to the right direction, I'd very much appreciate it.

Here's my code for the cylinder class

 public class Cylinder : Shape
{
    public Cylinder()
    {
    GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
        cylinder.transform.position = new Vector3(3, 0, 0);
        cylinder.transform.localScale = new Vector3(1.0f, Random.Range(1, 2)-1*Time.deltaTime, 1.0f);

        cylinder.GetComponent<MeshRenderer>().material.color = Random.ColorHSV();
        Destroy(cylinder, 30.0f);
    }
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
Kenneth Dionisi
  • 59
  • 1
  • 3
  • 8

3 Answers3

6

This can be done with the Time.deltaTime and Vector3.Lerp in a coroutine function. Similar to Rotate GameObject over time and Move GameObject over time questions. Modified it a little bit to do just this.

bool isScaling = false;

IEnumerator scaleOverTime(Transform objectToScale, Vector3 toScale, float duration)
{
    //Make sure there is only one instance of this function running
    if (isScaling)
    {
        yield break; ///exit if this is still running
    }
    isScaling = true;

    float counter = 0;

    //Get the current scale of the object to be moved
    Vector3 startScaleSize = objectToScale.localScale;

    while (counter < duration)
    {
        counter += Time.deltaTime;
        objectToScale.localScale = Vector3.Lerp(startScaleSize, toScale, counter / duration);
        yield return null;
    }

    isScaling = false;
}

USAGE:

Will scale GameObject within 20 seconds:

StartCoroutine(scaleOverTime(cylinder.transform, new Vector3(0, 0, 90), 20f));
Programmer
  • 121,791
  • 22
  • 236
  • 328
1

Check out Lerp. A general example of how to use it would be something like this:

float t = 0;
Update()
{
    t += Time.deltaTime;
    cylinder.localScale = new Vector3(1, Mathf.Lerp(2f, 1f, t/3f), 1); // shrink from 2 to 1 over 3 seconds;
}
ryeMoss
  • 4,303
  • 1
  • 15
  • 34
0

You will create a new monobehaviour script and add it to your primitive. Then you wil use "Update" method of monobehaviour (or use coroutine) for change object over time.

Monobehaviour must be look like this:

public class ShrinkBehaviour : MonoBehaviour
{
    bool isNeedToShrink;
    Config currentConfig;

    float startTime;
    float totalDistance;

    public void StartShrink(Config config)
    {
        startTime = Time.time;
        currentConfig = config;
        totalDistance = Vector3.Distance(currentConfig.startSize, currentConfig.destinationSize);
        isNeedToShrink = true;
        transform.localScale = config.startSize;
    }

    private void Update()
    {
        if (isNeedToShrink)
        {
            var nextSize = GetNextSize(currentConfig);

            if (Vector3.Distance(nextSize, currentConfig.destinationSize) <= 0.05f)
            {
                isNeedToShrink = false;
                return;
            }

            transform.localScale = nextSize;
        }
    }

    Vector3 GetNextSize(Config config)
    {
        float timeCovered = (Time.time - startTime) / config.duration;
        var result = Vector3.Lerp(config.startSize, config.destinationSize, timeCovered);
        return result;
    }

    public struct Config
    {
        public float duration;
        public Vector3 startSize;
        public Vector3 destinationSize;
    }
}

For using this, you must do next:

public Cylinder()
{
    GameObject cylinder = GameObject.CreatePrimitive(PrimitiveType.Cylinder);
    var shrink = cylinder.AddComponent<ShrinkBehaviour>();
    shrink.StartShrink(new ShrinkBehaviour.Config() { startSize = Vector3.one * 10, destinationSize = Vector3.one * 1, duration = 20f });
    cylinder.transform.position = new Vector3(3, 0, 0);

    cylinder.GetComponent<MeshRenderer>().material.color = Random.ColorHSV();
    Destroy(cylinder, 30.0f);
}

You must remember, monobehaviour-script must be in separate file, and must have name similar to monobehaviour-class name. For example, ShrinkBehaviour.cs;

Sergiy Klimkov
  • 530
  • 7
  • 15