栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

日常UE4自写C++静态函数分享

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

日常UE4自写C++静态函数分享

 

一、LerpTransformByCurve函数
可以根据曲线,平滑的对变换进行插值(按引用),相当于使用曲线替换Lerp节点的Alpha值。其返回值表示是否到达插值终点。参数解释:
const FTransform& Start    插值的起点变换

FTransform& Current    当前的变换(按引用),可以被曲线平滑改变

const FTransform& Target    插值的终点变换

const UCurveFloat* Curve    透明度曲线,其取值在0到1之间,以便进行Lerp插值

float& CurveTime    曲线的当前时间

const float& DeltaSeconds    场景时间

static bool LerpTransformByCurve(const FTransform& Start,FTransform& Current,const FTransform& Target,const UCurveFloat* Curve,float& CurveTime,const float& DeltaSeconds)
{
    if(Curve)
    {
        CurveTime = CurveTime + DeltaSeconds;
        float MinTime,MaxTime;
        Curve->GetTimeRange(MinTime,MaxTime);

        CurveTime = FMath::Clamp(CurveTime,MinTime,MaxTime);
        FTransform LerpTransform = UKismetMathLibrary::TLerp(Start,Target,Curve->GetFloatValue(CurveTime),ELerpInterpolationMode::DualQuatInterp);

        //直接赋值,不考虑过渡
        //Current = LerpTransform;
        //使用插值赋值较为平滑
        Current = UKismetMathLibrary::TInterpTo(Current,LerpTransform,DeltaSeconds,20.0f);

        if(CurveTime >= MaxTime)
        {
            CurveTime = 0.0f;
            return true;
        }
    }
    return false;
}
需要在Tick内使用。用法举例:

FTransform Start = 起始值;//假设已经赋值了
FTransform End = 终点值;//假设已经赋值了
float MyCurveTime = 0.0f;//假设从曲线起始时间向后进行插值
void AMyClass::Tick(float DeltaSeconds)
{
    Super::Tick(DeltaSeconds);

    //用一个bool控制是否进行插值
    if (bLerpMyTransform)
    {
      //用IsFinished取得返回值,如果为true表示已经插值完毕,如果为false表示还没有插值到终点
      bool IsFinished = LerpTransformByCurve(Start,MyTransform,End,MyCurve,MyCurveTime,DeltaSeconds);

      //ON TICK

      if (IsFinished)
      {
        //ON FINISHED

        //如果插值完毕,就停止插值
        bLerpMyTransform = false;
      }
      //在插值的过程中,MyTransform、MyCurveTime会一直保持更新,随时可以直接使用
    }
}
二、LerpFloatByCurve函数
static bool LerpFloatByCurve(const float& Start,float& Current,const float& Target,const UCurveFloat* Curve,float& CurveTime,const float& DeltaSeconds)
{
    if(Curve)
    {
        CurveTime = CurveTime + DeltaSeconds;
        float MinTime,MaxTime;
        Curve->GetTimeRange(MinTime,MaxTime);

        CurveTime = FMath::Clamp(CurveTime,MinTime,MaxTime);
        float LerpFloat = UKismetMathLibrary::Lerp(Start,Target,Curve->GetFloatValue(CurveTime));

        //直接赋值,不考虑过渡
        //Current = LerpFloat;
        //使用插值赋值较为平滑
        Current = UKismetMathLibrary::FInterpTo(Current,LerpFloat,DeltaSeconds,20.0f);

        if(CurveTime >= MaxTime)
        {
            CurveTime = 0.0f;
            return true;
        }
    }
    return false;
}
三、当然,更加优雅的方式

DECLARE_DELEGATE(FOnLerpTick);
DECLARE_DELEGATE(FOnLerpFinished);
DECLARE_DELEGATE(FOnLerpStop);
USTRUCT(BlueprintType)
struct FLerpTransformByCurve
{
    GENERATED_BODY()

public:
    FOnLerpTick OnTick;
    FOnLerpFinished OnFinished;
    FOnLerpStop OnStop;

    void StartLerp(UWorld* InWorld,FTransform& Target,FTransform const& A,FTransform const& B,UCurveFloat* Curve,float& CurveTime,
        float const& TimerRate,bool const& bForceStopExistingTimer=true)
    {
        if(bForceStopExistingTimer)
        {
            StopLerp(InWorld);
        }

        TimerCallBack = FTimerDelegate::CreateRaw(this, &FLerpTransformByCurve::LerpBody,InWorld,&Target,A,B,
            Curve,&CurveTime,TimerRate);
        InWorld->GetTimerManager().SetTimer(TimerHandle, TimerCallBack, TimerRate, true);
    }

    void StopLerp(const UWorld* InWorld) const
    {
        //ON STOP
        OnStop.ExecuteIfBound();

        InWorld->GetTimerManager().ClearAllTimersForObject(this);
    }

private:
    FTimerHandle TimerHandle;
    FTimerDelegate TimerCallBack;

    void LerpBody(UWorld* InWorld,FTransform* Target,FTransform A,FTransform B,UCurveFloat* Curve,float* CurveTime,float DeltaSeconds)
    {
        const bool IsFinished = this->LerpTransformByCurve(*Target,A,B,Curve,*CurveTime,DeltaSeconds);

        //ON TICK
        OnTick.ExecuteIfBound();

        if( IsFinished )
        {
            //ON FINISHED
            OnFinished.ExecuteIfBound();

            StopLerp(InWorld);
        }
    }

    static bool LerpTransformByCurve(FTransform& Target,const FTransform& A,const FTransform& B,const UCurveFloat* Curve,float& CurveTime,const float& DeltaSeconds)
    {
        if(Curve)
        {
            CurveTime = CurveTime + DeltaSeconds;
            float MinTime,MaxTime;
            Curve->GetTimeRange(MinTime,MaxTime);

            CurveTime = FMath::Clamp(CurveTime,MinTime,MaxTime);
            const FTransform LerpTransform = UKismetMathLibrary::TLerp(A,B,Curve->GetFloatValue(CurveTime),ELerpInterpolationMode::DualQuatInterp);

            Target = UKismetMathLibrary::TInterpTo(Target,LerpTransform,DeltaSeconds,20.0f);

            if(CurveTime >= MaxTime)
            {
                CurveTime = 0.0f;
                return true;
            }
        }
        return false;
    }
};
FLerpTransformByCurve LerpTransformByCurve;
//可以使用LerpTransformByCurve.OnFinished等来Bind其他事件
LerpTransformByCurve.StartLerp(GetWorld(),MyTransform,Start,End,MyCurve,MyCurveTime,G

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1009186.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号