我怎样才能使多次快速按下 F 时它无需等待就可以平滑地缩放对象 down/up?
How can I make that when pressing F fast many time it will scale the object down/up smooth without waiting?
第一个脚本用于 F 按下并调用 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);
}
}
}
第二个脚本进行缩放:
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());
}
}
}
问题是,如果我按 F,它开始放大但尚未完成缩放,我再次按 F 而不是开始缩小,就像暂停一样,如果我继续按 F,每次都会继续放大位.
但我想做的是当我第一次按 F 时开始放大,如果在缩放的中间我再次按 F 然后从当前缩放点开始缩小如果我再次按 F 然后像一个平滑的开关一样上下。
但是现在每次按F很多次就暂停
这就像我现在需要先等待缩放完成,然后才能再次按 F,否则它会暂停,我希望每次按 F 时它都会切换缩放 up/down .
您不需要多个函数来放大和缩小。一个人应该这样做。只需让它以比例量作为参数,然后重新使用该函数即可。比例尺 Min
和 Max
应该是 Vector3
而不是 float
因为这就是比例尺的表示方式并且您想要覆盖所有三个轴 (x,y,z)。
如何解决放大需要很长时间才能完成且按下按键时不切换方向的问题:
当您启动协程时,获取对该 运行 协程的引用。在再次启动协程之前,使用旧引用停止旧引用。就这么简单。重写整个代码比修复现有代码要好得多。
以下是您的代码的简化版本。确保从编辑器中设置 minSize
、maxSize
和 objectToScale
变量。如果您有任何问题,请参阅代码注释。
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;
}
}
第一个脚本用于 F 按下并调用 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);
}
}
}
第二个脚本进行缩放:
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());
}
}
}
问题是,如果我按 F,它开始放大但尚未完成缩放,我再次按 F 而不是开始缩小,就像暂停一样,如果我继续按 F,每次都会继续放大位.
但我想做的是当我第一次按 F 时开始放大,如果在缩放的中间我再次按 F 然后从当前缩放点开始缩小如果我再次按 F 然后像一个平滑的开关一样上下。
但是现在每次按F很多次就暂停
这就像我现在需要先等待缩放完成,然后才能再次按 F,否则它会暂停,我希望每次按 F 时它都会切换缩放 up/down .
您不需要多个函数来放大和缩小。一个人应该这样做。只需让它以比例量作为参数,然后重新使用该函数即可。比例尺 Min
和 Max
应该是 Vector3
而不是 float
因为这就是比例尺的表示方式并且您想要覆盖所有三个轴 (x,y,z)。
如何解决放大需要很长时间才能完成且按下按键时不切换方向的问题:
当您启动协程时,获取对该 运行 协程的引用。在再次启动协程之前,使用旧引用停止旧引用。就这么简单。重写整个代码比修复现有代码要好得多。
以下是您的代码的简化版本。确保从编辑器中设置 minSize
、maxSize
和 objectToScale
变量。如果您有任何问题,请参阅代码注释。
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;
}
}