如何让Unity Mixer混合器音量控制符合体感

Unity Mixer是什么

游戏中的声音轨道有很多,使用Unity提供Mixer混响可以很方便按组控制音量,只需要暴露变量给代码,就可以调用Mixer.SetFloat("变量", 数值),数值单位是db。

Unity Mixer修改音量为什么不符合体感

真实世界中的声音通过震动产生,
人耳感受最小声压 :
2×10^{-5} (db)
人耳感受最大声压:
2×10^{-1} (db)
Mixer采用的单位是db,最高0db,最低-80db,以模拟真实世界。但是按照直觉我们拖动进度条控制音量[0,-80]反而觉得音量变化不是线性的。这需要看声压级公式:
LP(db) = 10Log_{10}^{(\frac{p}{p0})}
推导求声压比公式:
(\frac{p}{p0}) = 10^\frac{Lp}{10}
当声压级按[0,-80]线性变化时,体感音量(声压比 p/p0)的变化是对数变化,因此如果需要体感音量按线性变化,那么就对LP进行转换。

convertToLp(volume:number){
    let lp = 10 * Math.Log10(volume)
    lp = Math.max(-80, lp)
    return lp
}

convertToVolump(db:number){
    let volume = Math.pow(10, db/10)
    //体感最小音量
    if(volume <= Math.pow(10, -5))
        volume = 0
    return volume
}

Unity Timeline 手动更新

this.director.timeUpdateMode = UnityEngine.Playables.DirectorUpdateMode.Manual

PlayeBetween(start:number, seconds: number){
    this.isPaused = false
    this.director.time = start
    this.targetTime = seconds
    this.director.Resume()
}
private UpdateTime(t:number){
    if(this.isPaused)return
    let director = this.director
    let targetTime = this.targetTime
    let deviation = this.devation
    if (director.time > targetTime + deviation)
    {
        director.time -= t;
        director.Evaluate();
    }
    else if (director.time < targetTime - deviation)
    {
        director.time += t;
        director.Evaluate();
    }
    else if (director.time != targetTime)
    {
        director.time = targetTime;
        director.Evaluate();
    }
}