ぼっちプログラマのメモ

Unreal Engineについて書いたりしてます

【UE5】AnimNodeのAlphaが0のときって本当に処理走らないの?

はじめに

AnimNodeのAlphaを0に設定するとそのノードの処理がアニメーション(各ボーン)に反映されなくなりますが、

GitHubにて「内部処理は動いてないの?大丈夫?」と質問されて少し不安になったので調べてみたという話 https://github.com/pafuhana1213/KawaiiPhysics/discussions/125

結論

処理が走る

  • Initialize_AnyThread
  • CacheBones_AnyThread
  • PreUpdate
  • Update_AnyThread
    • UpdateComponentPose_AnyThread
  • EvaluateComponentSpace_AnyThread
    • EvaluateComponentPose_AnyThread
  • AnimGraphNode, EditMode側の処理

処理が走らない

  • UpdateInternal
  • IsValidToEvaluate
  • EvaluateSkeletalControl_AnyThread
    • EvaluateComponentSpaceInternal

FAnimNode_SkeletalControlBase継承の自作AnimNodeでは、上記の「処理が走らない」関数にて処理を組んでおくのが良さそう

以下はぷち解説

ぷち解説

AnimNodeのAlphaの値は下記コードで使用され、その結果 FAnimNode_SkeletalControlBaseが持つActualAlphaの値が更新されます。

void FAnimNode_SkeletalControlBase::Update_AnyThread(const FAnimationUpdateContext& Context)
{
...
        // Apply the skeletal control if it's valid
        switch (AlphaInputType)
        {
        case EAnimAlphaInputType::Float : 
            ActualAlpha = AlphaScaleBias.ApplyTo(AlphaScaleBiasClamp.ApplyTo(Alpha, Context.GetDeltaTime()));
            break;
        case EAnimAlphaInputType::Bool :
            ActualAlpha = AlphaBoolBlend.ApplyTo(bAlphaBoolEnabled, Context.GetDeltaTime());
            break;
        case EAnimAlphaInputType::Curve :
            if (UAnimInstance* AnimInstance = Cast<UAnimInstance>(Context.AnimInstanceProxy->GetAnimInstanceObject()))
            {
                ActualAlpha = AlphaScaleBiasClamp.ApplyTo(AnimInstance->GetCurveValue(AlphaCurveName), Context.GetDeltaTime());
            }
            break;
        };

そして、下記コードのように ActualAlpha が 0 の場合だと一部処理がスキップされます。

void FAnimNode_SkeletalControlBase::EvaluateComponentSpace_AnyThread(FComponentSpacePoseContext& Output)
{
...

    // Apply the skeletal control if it's valid
    if (FAnimWeight::IsRelevant(ActualAlpha))
    {
        const USkeleton* Skeleton = Output.AnimInstanceProxy->GetSkeleton();
        const FBoneContainer& RequiredBones = Output.AnimInstanceProxy->GetRequiredBones();

        bool bIsValidToEvaluate;
        UE_DONT_INLINE_CALL bIsValidToEvaluate = IsValidToEvaluate(Skeleton, RequiredBones);
        if (bIsValidToEvaluate)
        {
            Output.SetNodeIds(CachedContext);

            UE_DONT_INLINE_CALL EvaluateComponentSpaceInternal(Output);

逆に言うと、ActualAlpha によるスキップ判定がない部分はAlphaが0であっても実行されます。

特にEditorモジュール側(AnimGraphNode, EditMode)はActualAlpha を全く考慮していないため、デバッグ描画処理にActualAlpha を考慮したコードを含める必要があります。

// ActualAlpha = FAnimNode_SkeletalControlBase::GetAlpha();
if (FAnimWeight::IsRelevant(ActualAlpha))
{

余談

上記対応を使うことでAlpha = 0 時にデバッグ表示を消す対応を入れることに成功したのですが、BlendノードなどでAnimNodeが評価されない場合における対応が抜けてることに気づきました。エンジンコードを色々調べたのですが良い方法が見つからず…ひとまず最後にノードを評価した時間が一定時間内だったらデバッグ表示するという対応で済ませました…ダサいので良い方法募集中… github.com

おしまい