How can i scale object slowly ?

I have two scripts and two problems.

The first script is when i press on F once it’s showing the object. Pressing F again will not show the object:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DroidMove : MonoBehaviour
{
    public GameObject droid;

    private float distance;
    private Camera cam;

    private void Start()
    {
        cam = GetComponent<Camera>();
        distance = Vector3.Distance(cam.transform.position, droid.transform.position);
        droid.SetActive(false);
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.F))
        {
            droid.SetActive(!droid.activeInHierarchy);   
        }
    }
}

The second script should scale the object slowly once from 0 to 1:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChangeScale : MonoBehaviour
{
    public GameObject objectToScale;

    private float _currentScale = InitScale;
    private const float TargetScale = 1.1f;
    private const float InitScale = 0f;
    private const int FramesCount = 100;
    private const float AnimationTimeSeconds = 7;
    private float _deltaTime = AnimationTimeSeconds / FramesCount;
    private float _dx = (TargetScale - InitScale) / FramesCount;
    private bool _upScale = true;
    private IEnumerator Breath()
    {
        while (true)
        {
            while (_upScale)
            {
                _currentScale += _dx;
                if (_currentScale > TargetScale)
                {
                    _upScale = false;
                    _currentScale = TargetScale;
                }
                objectToScale.transform.localScale = Vector3.one * _currentScale;
                yield return new WaitForSeconds(_deltaTime);
            }

            while (!_upScale)
            {
                _currentScale -= _dx;
                if (_currentScale < InitScale)
                {
                    _upScale = true;
                    _currentScale = InitScale;
                }
                objectToScale.transform.localScale = Vector3.one * _currentScale;
                yield return new WaitForSeconds(_deltaTime);
            }
        }
    }
   
    private void Update()
    {
        if (objectToScale.activeInHierarchy == true)
        {
            StartCoroutine(Breath());
        }
    }
}

The problems are in the ChangeScale script.

First problem is that i want to scale the object once from o to 1 (from 0,0,0 to 1,1,1) so i’m checking in the Update if the droid is active in hierarchy when i press on F then start the coroutine:

private void Update()
    {
        if (objectToScale.activeInHierarchy == true)
        {
            StartCoroutine(Breath());
        }
    }

But since it’s all the time true it keep changing the object scale non stop.

The second problem is changing the scaling time. I tried to change the variable AnimationTimeSeconds to 7 but it didn’t change much so i changed the FramesCount to 1000 so the first time the scaling was a bit slowly but then each time the scaling is getting faster and faster.

What i want is two things:

To change the scaling once. And to be able to control the scaling time.

I made it work well almost perfect as i wanted.

The first script i changed to:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DroidMove : MonoBehaviour
{
    public GameObject droid;
    public ChangeScale changeScale;

    private float distance;
    private Camera cam;

    private void Start()
    {
        cam = GetComponent<Camera>();
        distance = Vector3.Distance(cam.transform.position, droid.transform.position);
        droid.SetActive(false);
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.F))
        {
            droid.SetActive(!droid.activeInHierarchy);
            if (droid.activeInHierarchy == true)
                changeScale.Scale();
        }
    }
}

The second script i removed the Start and Update and using only a Scale method i did:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ChangeScale : MonoBehaviour
{
    public GameObject objectToScale;

    private float _currentScale = InitScale;
    private const float TargetScale = 1.1f;
    private const float InitScale = 0f;
    private const int FramesCount = 100;
    private const float AnimationTimeSeconds = 7;
    private float _deltaTime = AnimationTimeSeconds / FramesCount;
    private float _dx = (TargetScale - InitScale) / FramesCount;
    private bool _upScale = true;

    private IEnumerator Breath()
    {
        while (true)
        {
            while (_upScale)
            {
                _currentScale += _dx;
                if (_currentScale > TargetScale)
                {
                    _upScale = false;
                    _currentScale = TargetScale;
                }
                objectToScale.transform.localScale = Vector3.one * _currentScale;
                yield return new WaitForSeconds(_deltaTime);
            }

            while (!_upScale)
            {
                _currentScale -= _dx;
                if (_currentScale < InitScale)
                {
                    _upScale = true;
                    _currentScale = InitScale;
                }
                objectToScale.transform.localScale = Vector3.one * _currentScale;
                yield return new WaitForSeconds(_deltaTime);
            }
        }
    }

    public void Scale()
    {
        StartCoroutine(Breath());
    }
}

But now it’s scaling it up and down non stop and i want to scale it up only once.

take out the while(true)… then it does it only once

Agreed with @bigmisterb , plus I think you want to try commenting out the !upscale portion, as I imagine that is scaling it back down.

Just a quick question(not directed only to the op), does this code continue to run to the end after _upScale is set to false?
or does the coroutine checks if it should carry on only before it restarts?

while (_upScale)
            {
                _currentScale += _dx;
                if (_currentScale > TargetScale)
                {
                    _upScale = false;
                    _currentScale = TargetScale;
                }
                objectToScale.transform.localScale = Vector3.one * _currentScale;
                yield return new WaitForSeconds(_deltaTime);
            }

Please post a thread if you have a question, instead of semi-hijacking :slight_smile:
And show the entire code in question if you’re wondering about something … reading your question, I’m not 100% sure if that is part of the code or all of it, for example. :slight_smile:

It’s a part of the op’s Breath coroutine, i asked it here instead of another post because i’m fairly certain about the answer and i wanted to point the op at this problem

Ah okay, well hopefully the OP figured out what to do. In the original post, the coroutine would run indefinitely, because of the while(true) loop (as there is no break). Scale up, down, up, down… on n on :slight_smile:
I believe this was already sorted out in the answers given. Sorry I didn’t realize you were trying to answer, as well. :slight_smile: