简体   繁体   中英

How can I make that when pressing F fast many time it will scale the object down/up smooth without waiting?

The first script is for the F pressing and calling the ScaleChange:

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

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

    private bool toDisplay = false;

    private void Start()
    {
        droid.transform.localScale = new Vector3(0, 0, 0); 
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.F))
        {
            toDisplay = !toDisplay;
            changeScale.Scale(toDisplay);
        }
    }
}

The second script make the scaling:

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

public class ChangeScale : MonoBehaviour
{
    public GameObject objectToScale;

    private float _currentScale = InitScale;
    private const float TargetScale = 0.7f;
    private const float InitScale = 0f;
    private const int FramesCount = 10;
    private const float AnimationTimeSeconds = 0.1f;
    private float _deltaTime = AnimationTimeSeconds / FramesCount;
    private float _dx = (TargetScale - InitScale) / FramesCount;

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

    private IEnumerator ScaleDown()
    {
        bool downscaling = true;
        while (downscaling)
        {
            _currentScale -= _dx;
            if (_currentScale < InitScale)
            {
                downscaling = false;
                _currentScale = InitScale;
            }
            objectToScale.transform.localScale = Vector3.one * _currentScale;
            yield return new WaitForSeconds(_deltaTime);
        }
    }

    public void Scale(bool scaleUp)
    {
        if (scaleUp)
        {
            StartCoroutine(ScaleUp());
        }
        else
        {
            StartCoroutine(ScaleDown());
        }
    }
}

The problem is if I press on F and it start scaling up and not finished yet the scaling and I press F again instead start scaling down it's like pausing and if I keep pressing F it will keep scaling up each time a bit.

But what I want to do is when I press first time F start scaling up and if in the middle while scaling i'm pressing F again then from the current scaling point start scaling down and if I press F again then up and down like a smooth switch.

But now it's just pausing each time I press F many times.

It's like I need to wait now for the scaling to finish first before I can press F again if not it will just pause it and i want that each time I press F it will switch the scaling up/down.

You don't need multiple functions for scaling up and down. One should do it. Just make it take a scale amount as parameter then re-use that function. The scale Min and Max should be a Vector3 not float since that's how scale is represented and you want to cover all three axis (x,y,z).

How to fix the problem of scaling up taking so long to finish and not switching direction when key is pressed:

When you start a coroutine, get a reference to that running coroutine. Before you start the coroutine again, use the old reference to stop the old one. It's as simple as that. It's much better to re-write the whole code than to fix the existing one you have.

Below is a simplified version of your code. Make sure to set the minSize , maxSize and objectToScale variables from the Editor. See code comments if you have any question.

public GameObject objectToScale;
public Vector3 minSize;
public Vector3 maxSize;

private bool scaleUp = false;
private Coroutine scaleCoroutine;

// Use this for initialization
void Update()
{
    if (Input.GetKeyDown(KeyCode.F))
    {
        //Flip the scale direction when F key is pressed
        scaleUp = !scaleUp;

        //Stop old coroutine
        if (scaleCoroutine != null)
            StopCoroutine(scaleCoroutine);

        //Scale  up
        if (scaleUp)
        {
            //Start new coroutine and scale up within 5 seconds and return the coroutine reference
            scaleCoroutine = StartCoroutine(scaleOverTime(objectToScale, maxSize, 5f));
        }

        //Scale Down
        else
        {
            //Start new coroutine and scale down within 5 seconds and return the coroutine reference
            scaleCoroutine = StartCoroutine(scaleOverTime(objectToScale, minSize, 5f));
        }
    }
}

IEnumerator scaleOverTime(GameObject targetObj, Vector3 toScale, float duration)
{
    float counter = 0;

    //Get the current scale of the object to be scaled
    Vector3 startScaleSize = targetObj.transform.localScale;

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM