需求分析与类设计
编写能够通过一个函数调节音乐淡入淡出效果的类。
使用时将脚本挂载在AudioSource的物体上,其他脚本的物体能够访问物体上的这个类进行音量调节。
需要导入的外部成员变量:
1、本物体的AudioSource
2、目标音量
实现思路:
使用FadeMusic(目的音量,持续时间-多少秒)函数设置当前音乐的变化状态,计算出每次刷新的音量的变化值volumedelta。在Update函数中通过保存的volumedelta每次刷新时更改音量。在音乐达到目的音量附近时,停止音量变化,重置状态。
刷新的总变化量使用timedelta = durtime / Time.deltaTime获取,每次刷新的音量变化量用(target - start) / timedelta算出。这样的话,淡入淡出时间就会控制在deltatime(秒)内。注意执行一下除0判断。
代码实现
本人代码没有什么优化,仅供参考。(建议看后面的注意事项!)
public class MusicFade : MonoBehaviour
{
/*
* 挂载在audiosource类型的gameobj上,使用时调用objname.fadeMusic(volume,time)
*/
// Start is called before the first frame update
[SerializeField] private AudioSource Music;
[SerializeField] private float volumeDelta;
[SerializeField] private float targetvolume ;
[SerializeField] private bool isfading;
void Start()
{
Music = GetComponent<AudioSource>();
volumeDelta = 0;
volDecrease = false;
isfading = false;
}
// Update is called once per frame
void Update()
{
if (!isfading) return;
if(Math.Abs(Music.volume - targetvolume) >= Math.Abs(volumeDelta))
{
Music.volume += (float)volumeDelta;
Debug.Log("fading...");
}
else
{
Music.volume = targetvolume;
isfading = false;
}
}
public void FadeMusic(float targetVolume/*0-1*/, float durtime/*seconds*/)
{
Debug.Log("Music fade set target = " + targetVolume);
targetvolume = targetVolume;
if(Music == null) Music = GetComponent<AudioSource>();
float timedelta = durtime / Time.deltaTime;
if(timedelta > 0)
volumeDelta = (targetVolume - Music.volume) / timedelta;
else
{
volumeDelta = (targetVolume - Music.volume);
}
isfading = true;
}
public void FadeOut()
{
fadeMusic(0,1);
}
public void FadeIn()
{
fadeMusic(0.5f,1);
}
}
注意事项
1、似乎FadeMusic函数和本类的Update是有并发运行的?如果将isFading = true这个语句提前,会导致音量变化出错。
2、必须在FadeMusic内添加判断是否有AudioSource的引用,并且加上获取!其他脚本调用这个函数时,有可能本类对象还没有执行Awake函数。(或许写进构造函数会修正这个bug?)
3、gameObject用getComponent找到这个类的对象再调用成员函数。
参考资料:如何实现音频淡入淡出效果
以及谁能告诉我一下为什么编辑界面的强调部分框对了,展示部分的强调完全错了……debug不能
![](https://img-blog.csdnimg.cn/20210415211056390.png)