我想在Unity中创建一些萤火虫。我想增加光强度然后等待几秒钟,然后在Unity中减少它。当它们产生时,我希望它们增加光照强度,等待几秒钟然后淡出。如何以干净的方式创建这个“过程”?
private Light pointLight; // The light component of the firefly
private float minLuminosity = 0; // min intensity
private float maxLuminosity = 1; // max intensity
private float luminositySteps = 0.005f; // factor when increasing / decreasing
private float shineDuration = 3; // wait 3 seconds when faded in
private void Start()
{
pointLight = GetComponent<Light>();
pointLight.intensity = Random.Range(minLuminosity, maxLuminosity); // start with a random intensity
StartCoroutine(ChangeIntensity()); // start the process
}
private IEnumerator ChangeIntensity()
{
pointLight.intensity += luminositySteps; // increase the firefly intensity / fade in
yield return new WaitWhile(() => pointLight.intensity >= maxLuminosity); // wait for the maximum intensity
yield return new WaitForSeconds(shineDuration); // wait 3 seconds
pointLight.intensity -= luminositySteps;
yield return new WaitWhile(() => pointLight.intensity <= maxLuminosity); // wait for the minimum intensity
StartCoroutine(ChangeIntensity()); // do it again
}
很明显,协程在第一个WaitWhile()
永远停止了?如何创建这样的代码链?淡入或淡出时,我的意思是改变光强度。
答案 0 :(得分:4)
即使已经解决了这个问题,当前的解决方案只是递减变量,并且每帧都会创建新对象(WaitForSeconds
)。
在Unity中执行此操作的正确方法是使用Mathf.Lerp
和Time.deltaTime
。这种类型的操作是从Mathf.Lerp
到minLuminosity
的{{1}}。您可以在我的其他问题中阅读更多相关信息,以便使用其alpha分量here淡出/使用GameObject。
我从answer获取maxLuminosity
函数并移植它以使用fadeInAndOut
组件。这是一个简单的淡入淡出功能:
Light
现在,要创建所需的精确效果,即增加光照强度,然后等待几秒钟然后减小它,创建另一个调用上述函数的协同程序函数并等待它完成。你可以通过产生IEnumerator fadeInAndOut(Light lightToFade, bool fadeIn, float duration)
{
float minLuminosity = 0; // min intensity
float maxLuminosity = 1; // max intensity
float counter = 0f;
//Set Values depending on if fadeIn or fadeOut
float a, b;
if (fadeIn)
{
a = minLuminosity;
b = maxLuminosity;
}
else
{
a = maxLuminosity;
b = minLuminosity;
}
float currentIntensity = lightToFade.intensity;
while (counter < duration)
{
counter += Time.deltaTime;
lightToFade.intensity = Mathf.Lerp(a, b, counter / duration);
yield return null;
}
}
函数来做到这一点。注意如何在fadeInAndOut
循环之外声明WaitForSeconds
,以便每次都不会创建新的Object。
while
<强> USAGE 强>:
//Fade in and out forever
IEnumerator fadeInAndOutRepeat(Light lightToFade, float duration, float waitTime)
{
WaitForSeconds waitForXSec = new WaitForSeconds(waitTime);
while (true)
{
//Fade out
yield return fadeInAndOut(lightToFade, false, duration);
//Wait
yield return waitForXSec;
//Fade-in
yield return fadeInAndOut(lightToFade, true, duration);
}
}
答案 1 :(得分:1)
代码中的问题是您只应用了一次光度变化,因此永远不会达到WaitWhile
条件。我会将WaitWhile
更改为简单的while循环,然后使用WaitForEndOfFrame:
private IEnumerator ChangeIntensity()
{
while(true)
{
while(pointLight.intensity <= maxLuminosity)
{
pointLight.intensity += luminositySteps; // increase the firefly intensity / fade in
yield return new WaitForEndOfFrame();
}
yield return new WaitForSeconds(shineDuration); // wait 3 seconds
while(pointLight.intensity > minLuminosity)
{
pointLight.intensity -= luminositySteps;
yield return new WaitForEndOfFrame();
}
}
}
答案 2 :(得分:0)
所以我通过使用以下while循环来获得它
private IEnumerator ChangeIntensity()
{
while (true)
{
pointLight.intensity += isIncreasing ? luminositySteps : -luminositySteps;
if (pointLight.intensity <= minLuminosity)
isIncreasing = true;
if (pointLight.intensity >= maxLuminosity)
{
isIncreasing = false;
yield return new WaitForSeconds(shineDuration);
}
yield return null;
}
}