• UE4 自定義動(dòng)畫控制節(jié)點(diǎn)

    2021/1/2??????點(diǎn)擊:

    目的:在AnimationBlueprint中使用自定義動(dòng)畫控制節(jié)點(diǎn)。

    主要過程:

    1.      引用相關(guān)模塊。在Client.Build.cs文件中,PublicDependencyModuleNames.AddRange里加入”AnimGraphRuntime”,“AnimGraph”, “BlueprintGraph”,添加引用模塊后可在使用時(shí)直接包含頭文件名稱,而不用指定具體路徑。

    2.      實(shí)現(xiàn)AnimNode類,用于處理更新骨骼位置等具體邏輯;

    3.      實(shí)現(xiàn)AnimGraphNode類,用于在編輯器中顯示信息等;

    4.      編輯工程后即可在AnimationBlueprint中使用該節(jié)點(diǎn)

    下面以我的自定義動(dòng)畫節(jié)點(diǎn)CopyParentBone為例,該節(jié)點(diǎn)作用是更改當(dāng)前Component內(nèi)某骨骼的Transform為Parent Component內(nèi)同名稱骨骼的Transform:

    一、添加引用模塊

    Client.Build.cs


    PublicDependencyModuleNames.AddRange(new string[]   
            {   
                "Core",   
                "CoreUObject",   
                "Engine",   
                "InputCore",  
                "AIModule",  
                "GameplayTasks",  
                "Landscape",  
                "Foliage",  
                "AnimGraphRuntime",  
                "AnimGraph",  
                "BlueprintGraph"  
            });  


    二、AnimNode類


    Public/AnimNode_CopyParentBone.h


    /* 
     * \file AnimNode_CopyParentBone.h 
     * 
     * \author: Jia Zhipeng 
     * \date: 2016/02/24  
     */  
      
    #pragma once  
    #include "AnimNode_SkeletalControlBase.h"  
    #include "AnimNode_CopyParentBone.generated.h"  
      
    USTRUCT()  
    struct FAnimNode_CopyParentBone :public FAnimNode_SkeletalControlBase  
    //父類可以是FAnimNode_SkeletalControlBase或者FAnimNode_Base  
    //FAnimNode_SkeletalControlBase一般用于對(duì)骨骼的控制,通過EvaluateBoneTransforms更改骨骼位置。  
    //FAnimNode_Base一般用于對(duì)整體MeshBase的更改,通過Evaluate或者EvaluateComponentSpace更改Output.Pose更改全身的位置  
    //自定義類繼承父類后,override部分接口即可,以下是我用到的主要接口  
    {  
        GENERATED_USTRUCT_BODY()  
      
        /** Name of bone to control. **/  
        UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = SkeletalControl)  
        FBoneReference BoneToModify;  
          
    public:  
        //  Constructor  
        FAnimNode_CopyParentBone();  
      
    //  // FAnimNode_Base interface  
    //  顯示Debug信息  
        virtual void GatherDebugData(FNodeDebugData& DebugData) override;  
    //  // End of FAnimNode_Base interface  
      
        // FAnimNode_SkeletalControlBase interface  
    //  更改位置的邏輯實(shí)現(xiàn)函數(shù)  
        virtual void EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms) override;  
    //  判斷用到的骨骼是否有效   
    virtual bool IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones) override;  
        // End of FAnimNode_SkeletalControlBase interface  
      
    private:  
        // FAnimNode_SkeletalControlBase interface  
    //  初始化骨骼引用  
        virtual void InitializeBoneReferences(const FBoneContainer& RequiredBones) override;  
        // End of FAnimNode_SkeletalControlBase interface  
    };


    Private/AnimNode_CopyParentBone.cpp


    /* 
     * \file AnimNode_CopyParentBone.cpp 
     * 
     * \author: Jia Zhipeng 
     * \date: 2016/02/24  
     */  
      
    #include "Client.h"http://自己的Game.h  
    #include "AnimNode_CopyParentBone.h"  
      
    FAnimNode_CopyParentBone::FAnimNode_CopyParentBone()  
    {  
          
    }  
      
    //控制骨骼運(yùn)動(dòng)的邏輯實(shí)現(xiàn)。在OutBoneTransforms里Add需要修改的BoneTransform  
    void FAnimNode_CopyParentBone::EvaluateBoneTransforms(USkeletalMeshComponent* SkelComp, FCSPose<FCompactPose>& MeshBases, TArray<FBoneTransform>& OutBoneTransforms)  
    {  
        check(OutBoneTransforms.Num() == 0);  
        FTransform NewBoneTM = FTransform::Identity;  
        const FBoneContainer BoneContainer = MeshBases.GetPose().GetBoneContainer();  
          
        USceneComponent* ParentComponent = SkelComp->GetAttachParent();  
        if (ParentComponent)  
            NewBoneTM = ParentComponent->GetSocketTransform(BoneToModify.BoneName, RTS_Component);  
        else  
        {  
            UE_LOG(LogAnimation, Warning, TEXT("FAnimNode_CopyParentBone cannot get parent component"));  
        }  
        OutBoneTransforms.Add(FBoneTransform(BoneToModify.GetCompactPoseIndex(BoneContainer), NewBoneTM));  
    }  
      
    void FAnimNode_CopyParentBone::GatherDebugData(FNodeDebugData& DebugData)  
    {  
        FString DebugLine = DebugData.GetNodeName(this);  
      
        DebugLine += "(";  
        AddDebugNodeData(DebugLine);  
        DebugLine += FString::Printf(TEXT(" Target: %s)"), * BoneToModify.BoneName.ToString());  
        DebugData.AddDebugItem(DebugLine);  
      
        ComponentPose.GatherDebugData(DebugData);  
    }  
      
    bool FAnimNode_CopyParentBone::IsValidToEvaluate(const USkeleton* Skeleton, const FBoneContainer& RequiredBones)  
    {  
        return (BoneToModify.IsValid(RequiredBones));  
    }  
      
    void FAnimNode_CopyParentBone::InitializeBoneReferences(const FBoneContainer& RequiredBones)  
    {  
        BoneToModify.Initialize(RequiredBones);  
    }  


    三、AnimGraphNode

    Public/AnimGraphNode_CopyParentBone.h

    /* 
     * \file AnimGraphNode_CopyParentBone.h 
     * 
     * \author: Jia Zhipeng 
     * \date: 2016/02/24 
     * \purporse: 自定義動(dòng)畫節(jié)點(diǎn),在Parent Component中獲得與當(dāng)前Component的根骨骼同名的骨骼Transform,然后設(shè)置為當(dāng)前骨骼的Transform 
     */  
    #pragma once  
    #include "AnimGraphNode_SkeletalControlBase.h"  
    #include "AnimNode_CopyParentBone.h"  
    #include "AnimGraphNode_CopyParentBone.generated.h"  
      
    UCLASS(MinimalAPI)  
    class UAnimGraphNode_CopyParentBone : public UAnimGraphNode_SkeletalControlBase  
    {  
        GENERATED_UCLASS_BODY()  
      
        UPROPERTY(EditAnywhere, Category=Settings)  
        FAnimNode_CopyParentBone Node;  
      
        // UEdGraphNode interface  
    //  鼠標(biāo)懸浮在Node上的提示文本  
        virtual FText GetTooltipText() const override;  
    //  Node的名字文本     
    virtual FText GetNodeTitle(ENodeTitleType::Type TitleType) const override;  
        // End of UEdGraphNode interface  
      
    protected:  
        // UAnimGraphNode_SkeletalControlBase interface  
    //  返回controller的描述  
        virtual FText GetControllerDescription() const override;  
    //  返回引用的AnimNode  
        virtual const FAnimNode_SkeletalControlBase* GetNode() const override { return &Node; }  
        // End of UAnimGraphNode_SkeletalControlBase interface  
          
    };  

    Private/AnimGraphNode_CopyParenBone.cpp

    /* 
     * \file AnimNode_CopyParentBone.cpp 
     * 
     * \author: Jia Zhipeng 
     * \date: 2016/02/24  
     */  
      
    #include "Client.h"  
    #include "AnimGraphNode_CopyParentBone.h"  
      
    #define LOCTEXT_NAMESPACE "A3Nodes"  
    UAnimGraphNode_CopyParentBone::UAnimGraphNode_CopyParentBone(const FObjectInitializer& ObjectInitializer)  
    :Super(ObjectInitializer)  
    {  
    }  
      
    FText UAnimGraphNode_CopyParentBone::GetTooltipText() const  
    {  
        return LOCTEXT("AnimGraphNode_CopyParentBone_Tooltip", "Copy parent bone's transform to this component's root. Their names must be same");  
    }  
      
    FText UAnimGraphNode_CopyParentBone::GetNodeTitle(ENodeTitleType::Type TitleType) const  
    {  
        return LOCTEXT("AnimGraphNode_CopyParentBone_Title", "Copy Parent Bone");  
    }  
      
    FText UAnimGraphNode_CopyParentBone::GetControllerDescription() const  
    {  
        return LOCTEXT("CopyParentBone", "Copy Parent Bone");  
    }  
      
    #undef LOCTEXT_NAMESPACE

    參考內(nèi)容

    創(chuàng)建自定義動(dòng)畫節(jié)點(diǎn)

    https://www.unrealengine.com/zh-CN/blog/creating-custom-animation-nodes