<style>.lazy{display:none}</style> Skip to main content
Category

Tutorial

Unreal C++ Tutorial – Player Character Series – Punch – Part 6 – Review Lesson using Kicks !

By Development, Tutorial, Unreal One Comment

Hey guys,

Today we are finally back with the Player Character series , picking up where we left off, as well as incorporating all the previous tutorials into this lesson.

This time we are going to do a review lesson, where we go back over all the topics we covered earlier, and use them to implement a new set of attacks in the form of kicks.

 

The GitHub starter project can be found here as well as the final version with all the things.

The major component that is net new to this series is the inclusion of an additional Blend Node which you can read about here.

Take a look and we will see you next time.

Unreal Engine C++ Fundamentals – UAnimInstance

By Development, Tutorial, Unreal No Comments

Hey guys,

Yet again we are going to dive into Unreal Engine C++ Fundamentals by exploring UAnimInstance aka Animation Instance.

The project for this tutorial is available on GitHub as always.

What is a Anim Instance ?

An Anim Instance is the animation instance that drives our class.

Great ! So what is an Anim Instance ?

It’s really just a container and / or facade object that interacts with our class and any animations / montages that this class is currently executing.

What it allows us to do, is have fine grain control over the state and playback of our animations.

 

That’s great for you but what about my needs ?

Well since the

UAnimInstance
UAnimInstanceobject lets you take control of your animations it will be beneficial to a lot of game play mechanics.

Let’s just quickly glance over some of the parts of the Anim Instance to see how they could help by examining the PlayAnimMontage call.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
float ACharacter::PlayAnimMontage(class UAnimMontage* AnimMontage, float InPlayRate, FName StartSectionName)
{
UAnimInstance * AnimInstance = (Mesh)? Mesh->GetAnimInstance() : nullptr;
if( AnimMontage && AnimInstance )
{
float const Duration = AnimInstance->Montage_Play(AnimMontage, InPlayRate);
if (Duration > 0.f)
{
// Start at a given Section.
if( StartSectionName != NAME_None )
{
AnimInstance->Montage_JumpToSection(StartSectionName, AnimMontage);
}
return Duration;
}
}
return 0.f;
}
float ACharacter::PlayAnimMontage(class UAnimMontage* AnimMontage, float InPlayRate, FName StartSectionName) { UAnimInstance * AnimInstance = (Mesh)? Mesh->GetAnimInstance() : nullptr; if( AnimMontage && AnimInstance ) { float const Duration = AnimInstance->Montage_Play(AnimMontage, InPlayRate); if (Duration > 0.f) { // Start at a given Section. if( StartSectionName != NAME_None ) { AnimInstance->Montage_JumpToSection(StartSectionName, AnimMontage); } return Duration; } } return 0.f; }
float ACharacter::PlayAnimMontage(class UAnimMontage* AnimMontage, float InPlayRate, FName StartSectionName)
{
  UAnimInstance * AnimInstance = (Mesh)? Mesh->GetAnimInstance() : nullptr; 
  if( AnimMontage && AnimInstance )
  {
    float const Duration = AnimInstance->Montage_Play(AnimMontage, InPlayRate);

    if (Duration > 0.f)
    {
      // Start at a given Section.
      if( StartSectionName != NAME_None )
      {
        AnimInstance->Montage_JumpToSection(StartSectionName, AnimMontage);
      }

      return Duration;
    }
  }	

  return 0.f;
}

As you guys can see, the guys at Epic have taken a bunch of pieces of the Anim Instance class and wrapped them in a helper method.

So what is this method doing ?

  • Well it brings in the AnimInstance from our Mesh object by calling GetAnimInstance().
  • Then it validates that the montage we want to interact with is available and the Anim Instance is not null.
  • If that passes it then kicks off the Montage_Play method right on the Anim Instance by passing in the montage and the Play Rate.

So far so good.

  • We then look at a few more conditionals that just ensure the data that is required is available to us.
  • And then lastly it calls Montage_JumpToSection as the overall method takes in a StartSectionName value that determines the playback position.

 

Even Epic likes Anim Instances ? How do I subscribe to their newsletter ?

Well you can do that through their web site or simply by getting a reference to your local neighborhood Anim Instance and start performing some of these operations.

What are these common operations ?

There are a bunch of them but let’s go over the immediately meaningful ones.

Montage_Stop
Montage_Stop– stops the montage and blends in the next animation using the blend speed parameter. Good for killing montages mid playback.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// takes in a blend speed ( 1.0f ) as well as the montage
AnimInstance->Montage_Stop(1.0f, AttackMontage->Montage);
// takes in a blend speed ( 1.0f ) as well as the montage AnimInstance->Montage_Stop(1.0f, AttackMontage->Montage);
// takes in a blend speed ( 1.0f ) as well as the montage
AnimInstance->Montage_Stop(1.0f, AttackMontage->Montage);

 

Montage_Pause
Montage_Pause– pauses the current animation and freezes parts of the object tied to those animations. In our case we are able to pause a punch mid stream. Great for effects where you need to halt an animation, do some other activities and then resume.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// takes in the montage you want to pause
AnimInstance->Montage_Pause(AttackMontage->Montage);
// takes in the montage you want to pause AnimInstance->Montage_Pause(AttackMontage->Montage);
// takes in the montage you want to pause
AnimInstance->Montage_Pause(AttackMontage->Montage);

 

Montage_Resume
Montage_Resume– called after you call Montage_Pause as it will resume the playback of the animation from that point in time.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// takes in the montage you want to resume playback for
AnimInstance->Montage_Resume(AttackMontage->Montage);
// takes in the montage you want to resume playback for AnimInstance->Montage_Resume(AttackMontage->Montage);
// takes in the montage you want to resume playback for
AnimInstance->Montage_Resume(AttackMontage->Montage);

 

Montage_Play – triggers the playback of an animation based on various criteria like montage, speed, return type, playback start position and a control variable to stop other montages if they are currently executing.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// kicks off the playback at a steady rate of 1 and starts playback at 0 frames
AnimInstance->Montage_Play(AttackMontage->Montage, 1.0f, EMontagePlayReturnType::Duration, 0.0f, true);
// kicks off the playback at a steady rate of 1 and starts playback at 0 frames AnimInstance->Montage_Play(AttackMontage->Montage, 1.0f, EMontagePlayReturnType::Duration, 0.0f, true);
// kicks off the playback at a steady rate of 1 and starts playback at 0 frames
AnimInstance->Montage_Play(AttackMontage->Montage, 1.0f, EMontagePlayReturnType::Duration, 0.0f, true);

 

Montage_GetPosition
Montage_GetPosition– returns the current position of the playback frames as they are contained within the duration of the animation.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// returns current playback position
float CurrentPosition = AnimInstance->Montage_GetPosition(AttackMontage->Montage)
// returns current playback position float CurrentPosition = AnimInstance->Montage_GetPosition(AttackMontage->Montage)
// returns current playback position
float CurrentPosition = AnimInstance->Montage_GetPosition(AttackMontage->Montage)

 

Montage_IsPlaying
Montage_IsPlaying– returns a boolean to let the caller know if we have an active animation.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// checks to see if any animations in a montage are active
AnimInstance->Montage_IsPlaying
// checks to see if any animations in a montage are active AnimInstance->Montage_IsPlaying
// checks to see if any animations in a montage are active
AnimInstance->Montage_IsPlaying

 

Montage_JumpToSectionUAnimInstance
Montage_JumpToSectionUAnimInstance– moves the animation starting point to the location of the section as it’s setup in the Animation Montage.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// starts the animation at a specific section
AnimInstance->Montage_JumpToSection(StartSectionName, AnimMontage);
// starts the animation at a specific section AnimInstance->Montage_JumpToSection(StartSectionName, AnimMontage);
// starts the animation at a specific section
AnimInstance->Montage_JumpToSection(StartSectionName, AnimMontage);

 

Pretty neat eh !

As you can see, we get a lot freedom with access to anim instances as well as the ability to control our animations easily.

Not a huge collection of additional resources but here is the doc to the 

UAnimInstance
UAnimInstanceclass:

Unreal Engine C++ Fundamentals – UAnimNotify & UAnimNotifyState

By Development, Tutorial, Unreal 3 Comments

Hey guys,

Today we are going to continue exploring Unreal Engine C++ Fundamentals before we get back to our Player Character series by taking a look at Anim Notify and Anim Notify States.

You can find the GitHub project for this video in the usual location.

What is a Anim Notify ?

An Anim Notification or a

UAnimNotify
UAnimNotifyis a way of assigning events to parts of our animation that will be triggered at specific times of the animation playback.
UAnimNotifies
UAnimNotifiesreally only have one notification event. It either fires or it doesn’t.

 

Why do I care ?

Well most games have various animations and each animation may trigger different effects depending on it’s life cycle.
For example if we want to play back a noise that a weapon makes as our character slices it through the air we may want to use an

UAnimNotify
UAnimNotifyto trigger this event and then we can tie that event to the playback of our wooooshing sound.
We can also use notification events to trigger special effects, events in the game, UI updates, whatever you can imagine you can tie into this execution.

Ok smart guy what about Anim Notify States ?

Anim Notify States or

UAnimNotifyState
UAnimNotifyStateare almost identical to our Anim Notifies except for one difference and that is that Anim Notify States come with three events:

  • NotifyBegin
    • This even is fired once when the notification is first triggered.
  • NotifyTick
    • This event fires continuously every tick, during the execution of an
      UAnimNotifyState
      UAnimNotifyState.
  • NotifyEnd
    • This even fires once at the end of the
      UAnimNotifyState
      UAnimNotifyStateexecution.

 

Alright so we have these magical events, how do we code them ?

First let’s take a look at a

UAnimNotify
UAnimNotify

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// HEADER
UCLASS()
class UE4FUNDAMENTALS03_API UPunchThrowAnimNotify : public UAnimNotify
{
GENERATED_BODY()
public:
virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) override;
};
// SOURCE CPP
void UPunchThrowAnimNotify::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation)
{
// print method name to screen
GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Purple, __FUNCTION__);
}
// HEADER UCLASS() class UE4FUNDAMENTALS03_API UPunchThrowAnimNotify : public UAnimNotify { GENERATED_BODY() public: virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) override; }; // SOURCE CPP void UPunchThrowAnimNotify::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) { // print method name to screen GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Purple, __FUNCTION__); }
// HEADER

UCLASS()
class UE4FUNDAMENTALS03_API UPunchThrowAnimNotify : public UAnimNotify
{
  GENERATED_BODY()

public:
  virtual void Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) override;

};


// SOURCE CPP

void UPunchThrowAnimNotify::Notify(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation)
{
    // print method name to screen
    GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Purple, __FUNCTION__);
}

So, as you can see, by inheriting from

UAnimNotify
UAnimNotifywe are able to overwrite the “Notify” method and then print some stuff to the screen.
Pretty easy.

Now let’s see what a

UAnimNotifyState
UAnimNotifyStatelooks like

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// HEADER H
UCLASS()
class UE4FUNDAMENTALS03_API UPunchThrowAnimNotifyState : public UAnimNotifyState
{
GENERATED_BODY()
public:
virtual void NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration) override;
virtual void NotifyTick(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float FrameDeltaTime) override;
virtual void NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) override;
};
// SOURCE CPP
void UPunchThrowAnimNotifyState::NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration)
{
GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Yellow, __FUNCTION__);
}
void UPunchThrowAnimNotifyState::NotifyTick(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float FrameDeltaTime)
{
GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Yellow, __FUNCTION__);
}
void UPunchThrowAnimNotifyState::NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation)
{
GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Yellow, __FUNCTION__);
}
// HEADER H UCLASS() class UE4FUNDAMENTALS03_API UPunchThrowAnimNotifyState : public UAnimNotifyState { GENERATED_BODY() public: virtual void NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration) override; virtual void NotifyTick(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float FrameDeltaTime) override; virtual void NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) override; }; // SOURCE CPP void UPunchThrowAnimNotifyState::NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration) { GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Yellow, __FUNCTION__); } void UPunchThrowAnimNotifyState::NotifyTick(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float FrameDeltaTime) { GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Yellow, __FUNCTION__); } void UPunchThrowAnimNotifyState::NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) { GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Yellow, __FUNCTION__); }
// HEADER H

UCLASS()
class UE4FUNDAMENTALS03_API UPunchThrowAnimNotifyState : public UAnimNotifyState
{
  GENERATED_BODY()

public:
  virtual void NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration) override;
  virtual void NotifyTick(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float FrameDeltaTime) override;
  virtual void NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation) override;
  
};


// SOURCE CPP

void UPunchThrowAnimNotifyState::NotifyBegin(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float TotalDuration)
{
    GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Yellow, __FUNCTION__);
}

void UPunchThrowAnimNotifyState::NotifyTick(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation, float FrameDeltaTime)
{
    GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Yellow, __FUNCTION__);
}

void UPunchThrowAnimNotifyState::NotifyEnd(USkeletalMeshComponent* MeshComp, UAnimSequenceBase* Animation)
{
    GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Yellow, __FUNCTION__);
}

Cool ! Now show me how to tie those events into my game.

Well the majority of that is covered in the video but if you are curious this is what the events look like when you add them to the animations.

The way we added these notifications was by going to the bottom part of the animation montage labeled “Notifications”.
Then by Right Clicking we were able to pick our notifications.

This was all done from the Melee animation montage.

 

POINT OF NOTE:

UAnimNotify
UAnimNotifyand
UAnimNotifyStates
UAnimNotifyStatescan be added to single animations as well as animation montages. Which gives you a lot of freedom as to where and how you want these events to be triggered.

 

So there we go guys, with just a few lines of code and a bit of clicking we have notifications coming out of our animations and into our game.
If you would like to learn a little bit more about these various topics, check out the following links: