[UE4 C + +] preliminary use of animation and behavior tree related modules

Animation asset UAnimationAsset

type hierarchy structure

  • UObjectBase
    • UObjectBaseUtility
      • UObject
        • UAnimationAsset
          • UAnimSequenceBase
            • UAnimCompositeBase
              • Animation Synthesis of UAnimComposite
              • UAnimMontage animation Montage
            • UAnimSequence animation sequence (note root motion)
            • UAnimStreamable
          • UBlendSpaceBase
            • UBlendSpace mixed space
              • UAimOffsetBlendSpace aim offset blend space
            • UBlendSpace1D one dimensional mixed space
              • Uaimoffsetblendspace 1D one dimensional aiming offset hybrid space
          • UPoseAsset

C + + call

UAnimationAsset

  • Loaded are derived classes such as animation sequence and animation montage, which can be played directly

    // load
    UAnimationAsset* AnimDead_I;
    AnimDead_I = LoadObject<UAnimationAsset>(nullptr, TEXT("AnimSequence'/Game/Res/PolygonAdventure/Mannequin/Enemy/Animation/FightGroup/Enemy_Dead_I.Enemy_Dead_I'"));
    
    // Load constructor use
    UAnimationAsset* DeadAnim ; 
    static ConstructorHelpers::FObjectFinder<UAnimationAsset> StaticDeadAnim(TEXT("AnimSequence'/Game/Res/PolygonAdventure/Mannequin/Player/Animation/Player_Death.Player_Death'"));
    DeadAnim = StaticDeadAnim.Object;
    
    // Play, you can keep the last frame
    GetMesh()->PlayAnimation(DeadAnim, false);
    
    // Get duration
    AnimDead_I->GetMaxCurrentTime()
    

UAnimSequence

  • Can play directly

  • The length of time returned can be used for the behavior tree wait time

  • The returned transform can be used to Modify bone if necessary

  • Do not set cycle playback, you can freeze at the last frame

    // load
    static ConstructorHelpers::FObjectFinder<UAnimSequence> StaticAnimAttackSeq_III(TEXT("AnimSequence'/Game/Res/PolygonAdventure/Mannequin/Enemy/Animation/FightGroup/Enemy_Attack_III.Enemy_Attack_III'"));
    UAnimSequence* AnimAttackSeq_III;
    AnimAttackSeq_III = StaticAnimAttackSeq_III.Object;
    
    // Get duration
    AnimAttackSeq_III->GetPlayLength()
    // Get transform
    AnimAttackSeq_III->GetBoneTransform(OutputTrans, 0.f, CurrentPlayTime, true);
    

UAnimMontage

  • Animation fusion can be realized through slot

  • If necessary, you need to set it to freeze the last frame

  • The length of the corresponding UAnimSequence can be used for the waiting time of the behavior tree

  • It can be played after judging each frame; Or play when you want to call, such as characer and UBTTaskNode

    //play
    Montage_Play(AnimHurt);
    
    // Determine whether to play
    Montage_IsPlaying(AnimHurt)
    
    //Stop Montage
    void Montage_Stop(float InBlendOutTime, const UAnimMontage* Montage = NULL);
    Montage_Stop(0); // Stop all montages
    
    // Several methods related to the last frame of freeze frame
    GetMesh()->GlobalAnimRateScale = 0.f;
    GetMesh()->bNoSkeletonUpdate = true;
    GetMesh()->bPauseAnims = true;
    

Animation instance UAnimInstance and animation blueprint UAnimBlueprint

Article address https://www.cnblogs.com/shiroe/p/15634220.html

sketch

  • Generally, when creating an animation blueprint, you need to select the Parent Class of UAnimInstance
  • Therefore, after creating the UAnimInstance, write various variables and methods inside it, and then realize the communication between C + + and the blueprint through the animation blueprint. For example, variables are used for animation state machines, and events are used for calling animation notifications
  • When Montage is first used, it is usually called in character. Later, it is found that it can also be used in UAnimInstance

C + + call

  • Load animation blueprint
// Loading and setting
static  ConstructorHelpers::FClassFinder<UAnimInstance> StaticEnemyAnim(TEXT("AnimBlueprint'/Game/Blueprints/Enemy/BPA_Eneymy.BPA_Eneymy_C'"));
// GetMesh()->SetAnimationMode(EAnimationMode::AnimationBlueprint);
GetMesh()->SetAnimClass(StaticEnemyAnim.Class);

// character get * * UAnimInstance** 
SEAnim = Cast<UEnemyAnim>(GetMesh()->GetAnimInstance());

Behavior tree related modules

  • UBTService can be used for data update

  • UBTDecorator

  • UBlackboardData blackboard data can be inherited by Data Asset under Editor

    • reload-able

      virtual void PostLoad() override;
      
    • Add data, several types

      //Waiting time
      	FBlackboardEntry WaitTime;
      	WaitTime.EntryName = FName(TEXT("WaitTime"));
      	UBlackboardKeyType_Float* WaitTimeKeyType = NewObject<UBlackboardKeyType_Float>();
      	WaitTime.KeyType = WaitTimeKeyType;
      	Keys.Add(WaitTime);
      
      	//Enemy attack type
      	FBlackboardEntry AttackType;
      	AttackType.EntryName = FName(TEXT("AttackType"));
      	UBlackboardKeyType_Enum* EnemyAttackTypeKeyType = NewObject<UBlackboardKeyType_Enum>();
      	// Get enumeration type through reflection
      	EnemyAttackTypeKeyType->EnumType = FindObject<UEnum>(ANY_PACKAGE, *FString("EEnemyAttackType"), true);
      	EnemyAttackTypeKeyType->EnumName = FString("EEnemyAttackType");
      	AttackType.KeyType = EnemyAttackTypeKeyType;
      	Keys.Add(AttackType);
      
      	// Player pointer
      	FBlackboardEntry PlayerPawn;
      	PlayerPawn.EntryName = FName(TEXT("PlayerPawn"));
      	UBlackboardKeyType_Object* PlayerPawnKeyType = NewObject<UBlackboardKeyType_Object>();
      	PlayerPawnKeyType->BaseClass = ASLAiPlayerCharacter::StaticClass();
      	PlayerPawn.KeyType = PlayerPawnKeyType;
      	Keys.Add(PlayerPawn);
      
      	//Whether an action is completed
      	FBlackboardEntry ProcessFinish;
      	ProcessFinish.EntryName = FName(TEXT("ProcessFinish"));
      	ProcessFinish.KeyType = NewObject<UBlackboardKeyType_Bool>();
      	Keys.Add(ProcessFinish);
      
  • UBTTaskNode

    • Rewritable function

      // Override execution function
      virtual EBTNodeResult::Type ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
      //Override termination function
      virtual EBTNodeResult::Type AbortTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory) override;
      
      // Set the blackboard data to associate
      UPROPERTY(EditAnywhere,Category="Blackboard")
      		struct FBlackboardKeySelector WaitTime;
      UPROPERTY(EditAnywhere,Category="Blackboard")
      		struct FBlackboardKeySelector Destination;
      UPROPERTY(EditAnywhere,Category="Blackboard")
      		struct FBlackboardKeySelector IsActionFinish;
      
    • ExecuteTask

      • You can obtain character and controller through the parameter OwnerComp, and then access related functions or data
      • Can change blackboard data
      SEController = Cast<AEnemyController>(OwnerComp.GetAIOwner());
      SECharacter = Cast<AEnemyCharacter>(SEController->GetPawn());
      
      // Using the navigation system to obtain random points
      UNavigationSystemV1::K2_GetRandomReachablePointInRadius(SEController, WanderOrigin,DesLoc, WanderRadius);
      OwnerComp.GetBlackboardComponent()->SetValueAsVector(Destination.SelectedKeyName, DesLoc);
      
      // Play the animation and return the duration
      float AttackDuration = SECharacter->PlayAttackAction(EEnemyAttackType::EA_Normal);
      OwnerComp.GetBlackboardComponent()->SetValueAsFloat(WaitTime.SelectedKeyName, AttackDuration);
      
    • AbortTask

      • It is generally used for finishing work, such as clearing timer
    • Return value EBTNodeResult

      • According to the return value, let the behavior tree continue to execute the child node or jump out and return to the parent node
      // Return value
      return EBTNodeResult::Failed;
      return EBTNodeResult::Succeeded;
      return EBTNodeResult::Aborted;
      

Posted by gnathan87 on Thu, 02 Dec 2021 22:29:30 -0800