Smooth scaling of GameObject with conditions

I have a cube and want to scale it based on values I have (value range from 0 to 65535) and for a high value I want to scale it bigger and for low value smaller. The values are from another class and are sometimes constant or drop or rise sometimes. I tried the following :

void ChangeCubeSize(int value)
    {
      float change  = 1.0f;
 
     scaleChange = new Vector3(5, 5, 5);
     scaleChangeMin = new Vector3(2, 2, 2);
        if (value > 50000 )
        {
            change = 5.0f;
           // change += change*0.1f;
        } else if (value < 5000 ) {
           // change -= change*0.1f;
           change = 0.1f;
        }
        else
        {
            change = 2.0f;
           // change +=change* 0.05f;
        }
          cubeSizeChange.transform.localScale = Vector3.Lerp(scaleChange, scaleChangeMin, Time.deltaTime*change);


    }

but the cube would just abruptly change its size instead of smoothly. The above function is called in update. I read about using Coroutines for smoot scaling but they do not work well together with Update. What I am I doing wrong thats causing the cube not to change its size smoothly?

Thanks in advance

I would speculate you are not smoothly changing the third term passed to Lerp.

EDIT: yes, you do not want to pass something scaled by Time.deltaTime as this third term. Use this approach:

Try this approach instead to cause that third term to change smoothly:

Smoothing movement between any two particular values:

https://discussions.unity.com/t/812925/5

You have currentQuantity and desiredQuantity.

  • only set desiredQuantity
  • the code always moves currentQuantity towards desiredQuantity
  • read currentQuantity for the smoothed value

Works for floats, Vectors, Colors, Quaternions, anything continuous or lerp-able.

The code: https://gist.github.com/kurtdekker/fb3c33ec6911a1d9bfcb23e9f62adac4

Another approach would be to use a tweening package line LeanTween, DOTween or iTween.

Either way, here’s how to debug what you have:

You must find a way to get the information you need in order to reason about what the problem is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

What is often happening in these cases is one of the following:

  • the code you think is executing is not actually executing at all
  • the code is executing far EARLIER or LATER than you think
  • the code is executing far LESS OFTEN than you think
  • the code is executing far MORE OFTEN than you think
  • the code is executing on another GameObject than you think it is
  • you’re getting an error or warning and you haven’t noticed it in the console window

To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

Doing this should help you answer these types of questions:

  • is this code even running? which parts are running? how often does it run? what order does it run in?
  • what are the values of the variables involved? Are they initialized? Are the values reasonable?
  • are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

Knowing this information will help you reason about the behavior you are seeing.

You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as Debug.Log("Problem!",this);

If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

You could also just display various important quantities in UI Text elements to watch them change as you play the game.

If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: https://discussions.unity.com/t/700551 or this answer for Android: https://discussions.unity.com/t/699654

If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

Here’s an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

https://discussions.unity.com/t/839300/3

When in doubt, print it out!™

Note: the print() function is an alias for Debug.Log() provided by the MonoBehaviour class.

1 Like

First of all thanks for the detailed answer. I tried your approach with desiredQuantity etc. and it works but the changes made to the cube are too rapid. So my question is what exactly does the variable MovementPerSecond do and how can I make it that the variable doesnt change too fast?

You’d likely just need to decrease what you’re supplying to the final maxDistanceDelta parameter in Vector3.MoveTowards().

And in case Kurt’s reply was a little misunderstood, you would want to use Time.deltaTime when using Vector3.MoveTowards (but not when using Vector3.Lerp.

So instead of this :

cubeSizeChange.transform.localScale = Vector3.Lerp(scaleChange, scaleChangeMin,Time.deltaTime*change);

I should use it like this :

  cubeSizeChange.transform.localScale = Vector3.Lerp(scaleChange, scaleChangeMin,desiredQuantity);

with the desiredQuantity set in the conditions e.g :

  void ChangeCubeSize(int value)
    {
      float change  = 1.0f;
    
            scaleChange = new Vector3(5, 5, 5);
            scaleChangeMin = new Vector3(2, 2, 2);
        if (value > 50000f)
        {
            change = 5.0f;
            desiredQuantity = 1.0f;
           // change += change*0.1f;
        } else if (value < 5000 ) {
            desiredQuantity = 0.1f;
           // change -= change*0.1f;
           change = 5.0f;
        }
        else
        {  
            change = 3.0f;
            desiredQuantity = 0.5f;
           // change +=change* 0.05f;
        }
          cubeSizeChange.transform.localScale = Vector3.Lerp(scaleChange, scaleChangeMin,desiredQuantity);


    }

and the function:

{
        // Every frame without exception move the currentQuantity
        // towards the desiredQuantity, by the movement rate:
        currentQuantity = Mathf.MoveTowards(
            currentQuantity,
            desiredQuantity,
            MovementPerSecond * Time.deltaTime);
           
        // Note: use Mathf.MoveTowardsAngle() if the quantity is in degrees
    }

which I call in Update like this :

void Update()
    {
      ChangeCubeSize(value);
          ProcessMovement();
 
    }

The thing is that the changes are too fast and even with the above changes, I thought about using SmoothDamp but I dont know if it will improve. Do you have any suggestion how could I achieve this with smoother transitions?

That’s not quite what Kurt suggested.

This line is likely still the problem:

cubeSizeChange.transform.localScale = Vector3.Lerp(scaleChange, scaleChangeMin,desiredQuantity);

Vector3.Lerp isn’t what you want to use here. You want to replace this with a .MoveTowards() call.

For the code above you probably want to use currentQuantity instead of desiredQuantity in the Lerp. Because currentQuanity is the one which changes smoothly, but desired desired is the one you set instantly.

I disagree with spiney199 last comment. Vector.Lerp would be fine for mapping from currentQuanity (which is smoothly changed in the 0-1 range using MoveTowards).

I switched it with MoveTowards() but there were merely any changes to the cube it stayed the same size with a size diffrence of ±= 1.

This one was a little bit better now I just have to change the MovementPerSecond Variable and find the sweet spot for it

Yeah I will try out some things and just change MoveTowards a little bit