Попытка увеличить масштаб кубов в единице, а затем уменьшить, когда он достигнет определенного числа

#c# #unity3d

Вопрос:

Вот как я собираюсь это сделать:

 if(transform.localScale.x > 7)
{
    for(int i = 7; i > 1; i--)
    {
        transform.localScale -= new Vector3(1, 1, 1) * Time.deltaTime;
    }
}
else
{
    transform.localScale  = new Vector3(1, 1, 1) * Time.deltaTime;
}
 

Оператор else выполняется для увеличения масштаба, и когда он достигает 7, оператор if должен уменьшить его обратно до 1 благодаря циклу for, который должен выполняться в течение 6 итераций и уменьшать масштаб в 6 раз. Но только часть else работает должным образом, когда масштаб достигает 7, он просто уменьшается до 6, а затем возвращается к 7 через секунду. Он не доходит до 1.

Ответ №1:

Вы знаете, что весь ваш for цикл будет выполняться немедленно в пределах одного кадра? и вы умножаете это на Time.deltaTime то, что при условии, что 60 кадров в секунду будет значением около 0.0166666666... .

Итак, то, что вы делаете в цикле, в основном просто равносильно выполнению

 transform.localScale -= Vector3.one * 6 * 0.017f;
 

Прямо в следующем кадре вы можете снова оказаться ниже, чем 7 => вы попадаете в else дело и снова увеличиваете масштаб.

Поэтому в следующем кадре он уже снова уменьшит его и т. Д


Насколько я понимаю, вам скорее нужен эффект пин-понга между двумя масштабами.

Я бы предпочел использовать что-то вроде

 // adjust via the Inspector
public float speed = 1;
public float amplitude = 7f;

private Vector3 originalScale;
private float timePassed;

private void Start()
{
    originalScale = transform.localScale;
}

private void Update()
{
    timePassed  = Time.deltaTime * speed;

    // see https://docs.unity3d.com/ScriptReference/Mathf.PingPong.html
    transform.localScale = originalScale * (1   Mathf.PingPong(timePassed, amplitude - 1));
    // or with ease-in and ease-out
    //transform.localScale = originalScale * (1   (amplitude - 1) * Mathf.SmoothStep(0, 1, Mathf.PingPong(timePassed, 1)));
}
 

Где Mathf.PingPong

возвращает значение, которое будет увеличиваться и уменьшаться между значением 0 и длиной.


Или, если вам действительно нужно другое увеличение и уменьшение продолжительности, я бы предпочел предложить сопрограмму типа

 // adjust via the Inspector
public float increaseDuration = 1f;
public float decreaseDuration = 7f;

public float amplitude = 7f;

private IEnuemerator Start()
{
    var originalScale = transform.localScale;
    var maxScale = originalScale * amplitude;

    while(true)
    {
        for(var timePassed = 0f; timePassed < increaseDuration; timePassed  = Time.deltaTime)
        {
            var factor = timePassed / increaseDuration;
            // optinal add ease-in and ease-out
            //factor = Mathf.SmoothStep(0, 1, factor);

            transform.localScale = Vector3.Lerp(originalScale, maxScale, factor);

            yield return null;
        }

        for(var timePassed = 0f; timePassed < decreaseDuration; timePassed  = Time.deltaTime)
        {
            var factor = timePassed / decreaseDuration;
            // optinal add ease-in and ease-out
            //factor = Mathf.SmoothStep(0, 1, factor);

            transform.localScale = Vector3.Lerp(maxScale, originalScale, factor);

            yield return null;
        }
    }
}
 

Ответ №2:

Вы можете создать другую переменную, например:

 public bool isDecreasing=false;

if(!isDecreasing amp;amp; transform.localScale.x > 7)
{
   isDecreasing=true
}else if(isDecreasingamp;amp;transform.localScale.x==1)
{
   isDecreasing=false
}

if(isDecreasing)
{
   transform.localScale -= new Vector3(1, 1, 1) * Time.deltaTime;
}else
{
   transform.localScale  = new Vector3(1, 1, 1) * Time.deltaTime;
}
 

Комментарии:

1. Это все равно будет выполнять весь цикл в одном кадре, хотя, скорее всего, kin of в конечном итоге приведет к тому же поведению