游戏开发中经常要进行插值处理,这个东西处理虽然不复杂,但如果自己重新做,还是要写额外的代码,好消息是,Unreal已经为我们提供了插值助手——FAlphaBlend。
我们以一个非常简单的应用场景来说明FAlphaBlend的用处:屏幕的淡出处理,即游戏画面逐渐变暗直至完全变黑。更详细的描述可能是:要求2秒内屏幕逐渐变黑。
我们先来看一下FAlphaBlend的主要成员
struct FAlphaBlend
{
/** Blend Time */
//这个就是插值整个过程的处理时间,比如我们这里是2秒
UPROPERTY(EditAnywhere, Category = "Blend")
float BlendTime;
/** Internal Lerped value for Alpha */
//这个是当前的插值进度百分比,比如时间来到1秒后,它的值就是0.5(相当于2秒来说)
float AlphaLerp;
/** Resulting Alpha value, between 0.f and 1.f */
float AlphaBlend;
/** Time left to reach target */
//还剩下的插值时间,比如时间过了0.5秒后,它的值就是1.5
float BlendTimeRemaining;
/** The current blended value derived from the begin and desired values.
* This value should not change unless Update.
*/
//当前时间得到的插值结果,假如我们是线性插值,那么在1秒的时候,它的值是0.5
float BlendedValue;
/** The Start value. It is 'from' range */
//插值区间起始值,我们这里开始的透明度是0,所以它的值就是0
float BeginValue;
/** The Target value. It is 'to' range */
//插值区间目标值,我们这里结束的透明度是1,所以它的值就是1
float DesiredValue;
}
以上代码用注释/**/标注的是Unreal自己的注释,//是我额外添加的注释,针对我们的应用场景进行说明。
细心的同学可能会发现,里面还有一个成员AlphaBlend,我没有对它进行中文注释,其实它也是一个插值。那它也是插值,AlphaLerp也是插值,怎么有两个插值?它俩有什么区别?
AlphaLerp是直接的插值,它是BlendTime的线性结果,比如2秒来说,当0.5秒的时候的,AlphaLerp=0.5/2=0.25,当1秒的时候,AlphaLerp=1/2=0.5。
而AlphaBlend是结果的插值,根据不同的插值算法,它的值是不一样的。我们想平均地调整透明度,那就用线性算法,它的值和AlphaLerp一致。如果我们想透明度开始黑得慢一点,后面黑得快一点,则可能采用y= x^2算法,则当Alphalerp=0.5的时候,AlphaBlend=0.5*0.5=0.25。这就是它的注释/** Resulting Alpha value, between 0.f and 1.f */的意思所在,它才是结果插值。我们用0.25在透明度0~1之间进行取值,这里我们的例子是0~1,也可能是其他参数,比如高度0~100,则0.25对应的就是25。所以AlphaBlend的值取决于AlphaLerp和我们采用的算法。
FAlphaBlend里面有个重要的静态成员函数,处理的就是AlphaLerp到AlphaBlend的转换
/** Converts InAlpha from a linear 0...1 value into the output alpha described by InBlendOption
* @param InAlpha In linear 0...1 alpha
* @param InBlendOption The type of blend to use
* @param InCustomCurve The curve to use when blend option is set to custom
*/
static float AlphaToBlendOption(float InAlpha, EAlphaBlendOption InBlendOption, UCurveFloat* InCustomCurve = nullptr);
InAlpha传入的就是AlphaLerp
InBlendOption是个枚举,表示采用的转换算法
InCustomCurve是个CurveFloat,这个用来处理更加定制化的需求。
所以FAlphaBlend的使用过程是:设置好BlendTime(即插值区间要进行的时间),然后每帧调用Update函数,这个函数内部会计算出当前时间对应的AlphaLerp,并根据BlendOption算出真正的AlphaBlend,然后用这个AlphaBlend在[BeginValue,DesiredValue]进行线性取值得到BlendValue。
之后我们想用结果值的时候,直接使用BlendValue即可。
对于一些常用的转换算法,我们可以通过设置BlendOption来达到目的,但更加复杂的,BlendOption就无能为力了,这个时候我们就可以使用CurveFloat。我们可以把CurveFloat理解为一个转换函数,给定X,返回Y,非常棒的是Unreal里面有专门的曲线编辑器来编辑CurveFloat,假如我们在变黑的过程中是这样的表现:快速变黑,然后恢复透明,再逐渐地变黑。我们就可以定制曲线,来处理AlphaLerp(即X)到AlphaBlend(即X)的转换,可能如下图