Tag

game dev

Unreal Engine C++ Fundamentals – Using Tags with Transformations !

By | Development, Tutorial, Unreal | No Comments

Hey guys,

Today we resume our C++ Fundamentals lessons by looking at interfaces and how they can help simply our life by allowing for common contracts to be shared by different game actors.

As usual you can find the start project on our GitHub page.

What are these tags ? And why do I care ?

Tags are essentially a collection of strings that can be applied to an Actor or an Actors Component and then referenced by other Actors or parts of the game world by those tags.

Very similar to using tags on a blog to include metadata for search engines to query … like this blog !

Tags ?! We don’t need to no stinking tags !

Sure you do, and they are really easy to use which is why this post is going to be super short.

Take a look, in this case we are displaying all tags for a specific actor.

// iterate over all of our actors
for(TActorIterator<AActor> ActorIterator(GetWorld()); ActorIterator; ++ActorIterator)
{
  AActor* Actor = *ActorIterator;
  // ensure actor is not null
  // ignore self if found
  // ensure we find actors of a specific interface only
  if(Actor && Actor != this && Actor->GetClass()->ImplementsInterface(UInteractiveActor::StaticClass()))
  {
    // display all available tags for an actor
    for(FName Tag : Actor->Tags)
    {
     	GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Cyan, Tag.ToString());
    }
  }
}

We can also just check for a specific tag without iterating over all of them by using ActorHasTag method.

if(Actor->ActorHasTag(TagToCheck))
{
    IInteractiveActor::Execute_Interact(Actor);		
}

Wait you forgot about lerping ? What is lerping !?

Lerping is a way of translating between vector A and vector B over some period of time.

For example if you need to scale an object from one size to another you can use FMath::Lerp to accomplish this.

BaseMesh->SetWorldScale3D(FMath::Lerp(BaseMesh->GetComponentScale(), FVector(2.f, 2.f, 2.f), 0.05f));

In this example we go from vector A ( GetComponentScale() of our mesh ) to vector B ( 2x the size ) over a period of time represented by 0.05f time.

Take a look.

That’s it folks, not much more reading but here are a few links for you to check out:

Unreal Engine C++ Fundamentals – Interfaces!

By | Development, Tutorial, Unreal | 3 Comments

Hey guys,

Today we resume our C++ Fundamentals lessons by looking at interfaces and how they can help simply our life by allowing for common contracts to be shared by different game actors.

As usual you can find the start project on our GitHub page.

What is an interface ? Tell me !

An interface is an abstract definition of a contract. What this means is an interface defines how our class can be interfaced ( hah ! ) with while keeping the implementation details away.

More than that it allows us to create a common method signature between various disparate objects.

Consider I have an interface that has a method on it called “DoStuff” and I have two objects, Dog and Person, that inherit this interface. When I call Dog->DoStuff he may perform a trick while if I call the same method of Person->DoStuff he may tell me to fuck off and to stop bothering them. But from the point of view of the code interacting with those actors it’s the same behavior.

This allows for a lot of re-use and generic implementations while keeping the details of those implementations specific.

This all seems very abstract, show me code !

So let’s take a look at how an interface class is structured

UINTERFACE(MinimalAPI)
class UInteractiveActor : public UInterface
{
  GENERATED_BODY()
};

/**
 * 
 */
class UE4FUNDAMENTALS09_API IInteractiveActor
{
  GENERATED_BODY()

  // Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:

  UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Interact")
  void Interact();
};

As you can see it’s pretty thin in definition, we simply have a class that inherits from UInterface and then defines the method signature of “Interact”.

Excellent now we are cooking with fire, now what ?

Once we have the interface in place we now start including it on our objects. Let’s take a look at our InteractiveProp.

UCLASS()
class UE4FUNDAMENTALS09_API AInteractiveProp : public AActor, public IInteractiveActor
{
  GENERATED_BODY()
  
public:	
  // Sets default values for this actor's properties
  AInteractiveProp();

  UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Interact")
  class UStaticMeshComponent* BaseMesh;

protected:
  // Called when the game starts or when spawned
  virtual void BeginPlay() override;

public:	
  // Called every frame
  virtual void Tick(float DeltaTime) override;

  UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Interact")
  void Interact();	// prototype declaration
  virtual void Interact_Implementation() override;	// actual implementation of our interact method

private:
  bool bIsBig;
};

The major thing to note is that in order to leverage the interface, we modify our class signature to bring in “IInteractiveActor”

class UE4FUNDAMENTALS09_API AInteractiveProp : public AActor, public IInteractiveActor

Then we overwrite the Interact method by first declaring the prototype method signature and then the implementation one. Please note that the “_Implementation” is important and has to be exact for the reflection mechanic in Unreal to process your interface + implementation.

UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "Interact")
void Interact();	// prototype declaration
virtual void Interact_Implementation() override;	// actual implementation of our interact method

So that was pretty straight forward, now how do I use these guys ?

To execute interface definitions we have a few ways of going about.

First we need to determine if an object uses an interface and we have two ways of checking that.

  1. Based on the ImplementsInterface check
  2. Using a cast to an interface object

Here is the first example

InteractHit.GetActor()->GetClass()->ImplementsInterface(UInteractiveActor::StaticClass())

And the second one

IInteractiveActor* InteractiveActor = Cast<IInteractiveActor>(InteractHit.GetActor());
if(InteractiveActor)
{
  // do stuff
}

Once you determine if an object has an interface the way you execute a call on that object is by passing it into the interface “Execute_” call.

IInteractiveActor::Execute_Interact(InteractHit.GetActor());

This basically says, for interface InteractiveActor Execute the method Interact and pass in our Actor on which that method will be triggered.

Here is a full code block that does this logic using a line trace fired from the player against an object.

void AUE4Fundamentals09Character::Interact()
{
  FVector Start;
  FVector End;

  FVector PlayerEyesLoc;
  FRotator PlayerEyesRot;

  GetActorEyesViewPoint(PlayerEyesLoc, PlayerEyesRot);

  Start = PlayerEyesLoc;
  End = PlayerEyesLoc + (PlayerEyesRot.Vector() * LineTraceDistance);

  FCollisionQueryParams TraceParams(FName(TEXT("InteractTrace")), true, this);

  FHitResult InteractHit = FHitResult(ForceInit);

  bool bIsHit = GetWorld()->LineTraceSingleByChannel(InteractHit, Start, End, ECC_GameTraceChannel3, TraceParams);

  if(bIsHit)
  {
    Log(ELogLevel::WARNING, InteractHit.Actor->GetName());
    // start to end, green, will lines always stay on, depth priority, thickness of line
    DrawDebugLine(GetWorld(), Start, End, FColor::Green, false, 5.f, ECC_WorldStatic, 1.f);

    // implements interface
    if(InteractHit.GetActor()->GetClass()->ImplementsInterface(UInteractiveActor::StaticClass()))
    {
      IInteractiveActor::Execute_Interact(InteractHit.GetActor());
    }
  }
}

That’s it folks !

In addition to the video here are a few resources for further reading:

 

Unreal Engine C++ Fundamentals – AHUD, UUserWidget and UWidgetAnimation

By | Development, Tutorial | No Comments

Hey guys,

We are going to continue our C++ Fundamentals lessons by creating a custom HUD using AHUD class, then adding a custom widget to the HUD using UUserWidget and finally rounding things off by adding some UWidgetAnimations to make the whole thing look a bit more pretty.

As usual you can find the starter project on our GitHub page.

Hold up, lets get some background on all this stuff first !

HUD – heads.up.display. this is a way of projecting various bits of information in the form of text, images, animations, etc to inform the player as to what is happening to him, other things, or his environment.

Alternatively a hud can also represent menu screens, credits, etc.

Essentially they are the large canvas on which various components and widgets will be displayed on.

For example:
– hud that show cases all the player attributes like health, mana and stamina
– options menu for configuring graphics properties
– scrolling credits

User Widget – a single purpose component that you can attach to various locations on the hud as well as the view port. this is normally either a single “ui thing” or a logical grouping of “ui things”.

For example:
– a cross hair in a FPS game
– health and mana bars on top of each other
– speed gauge in a car sim

Widget Animation – are user widget components responsible for handling the animation for all the various components added to the user widget.

This includes manipulation of states like transformation, visibility, color and opacity. Which allows designers to create various fun and exciting ways of presenting data and feedback to the player.

Example:
– health bar is actually red liquid that boils away as the player takes damage
– damage indicators that show up when a player hits something and proceed to fall to the ground while fading away

That’s better, now what ?

Well lets take a look at our HUD class and what we can do with it.

UCLASS()
class UE4FUNDAMENTALS08_API AInGameHUD : public AHUD
{
  GENERATED_BODY()

public:
  AInGameHUD();

  // Primary draw call for the HUD.
  virtual void DrawHUD() override;

  virtual void BeginPlay() override;

  virtual void Tick(float DeltaSeconds) override;

  UFUNCTION()
  void UpdateComboCount(int32 Value);

  UFUNCTION()
  void ResetCombo();

  UPROPERTY(EditDefaultsOnly, Category = "Interactive")
  TSubclassOf<UUserWidget> HitComboWidgetClass;

private:
  UHitComboWidget* HitComboWidget;
};

Similar layout to our player or prop classes but you get a few extra functions like DrawHUD() that allows you to control the various aspects of screen components and widgets.

We also include a TSubclassOf<UUserWidget> that allows us to include various custom widget components as part of this HUD.

void AInGameHUD::BeginPlay()
{
  Super::BeginPlay();

  if (HitComboWidgetClass)
  {
    HitComboWidget = CreateWidget<UHitComboWidget>(GetWorld(), HitComboWidgetClass);

    /** Make sure widget was created */
    if (HitComboWidget)
    {
      /** Add it to the viewport */
      HitComboWidget->AddToViewport();
    }
  }
}

The important method here is the one that instantiates the custom widget class and adds it to our view port.

void AInGameHUD::UpdateComboCount(int32 Value)
{
  if (HitComboWidget)
  {
    HitComboWidget->UpdateComboCount(Value);
  }
}

This is just an example of how we would call our user widget via our hud.

Great we have a HUD but what else do we need ?!

So let’s examine our user widget to see what makes it tick.

UCLASS()
class UE4FUNDAMENTALS08_API UHitComboWidget : public UUserWidget
{
  GENERATED_BODY()
public:
  UHitComboWidget(const FObjectInitializer& ObjectInitializer);

  virtual void NativeConstruct() override;

  UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
  class UTextBlock* TXTCombo;

  void UpdateComboCount(int32 Value);

  void ResetCombo();

  void StoreWidgetAnimations();

  UWidgetAnimation* GetAnimationByName(FName AnimationName) const;

private:
  TMap<FName, UWidgetAnimation*> AnimationsMap;

  UWidgetAnimation* ComboFadeAnimation;
  UWidgetAnimation* ComboShakeAnimation;
};

As we can see in the header the deafult constructor for a UUserWidget is a bit different as it expects an ObjectInitializer to be passed in.

We also don’t have a BeginPlay but rather we expose NativeConstruct which esentially behaves the same way and loads stuff after the constructor is already loaded.

UPROPERTY(EditAnywhere, BlueprintReadWrite, meta = (BindWidget))
class UTextBlock* TXTCombo;

This bit here allows us to auto bind by name to a component on the user widget. In this case we are looking for a UTextBlock of name TXTCombo.

[ insert warning image ]

NOTE: You will get warnings if these attributes are not present.

And lastly we have our declared animations.

Ok, moving on the cpp file.

void UHitComboWidget::NativeConstruct()
{
  Super::NativeConstruct();

  StoreWidgetAnimations();

  ComboFadeAnimation = GetAnimationByName(TEXT("ComboFade"));
  ComboShakeAnimation = GetAnimationByName(TEXT("ComboShake"));
}

In the native construct we do a few things, we first use the StoreWidgetAnimations function to populate a map of animations keyed by name.

We then use that data to populate our animation variables by their names of ComboFade and ComboShake respectively.

void UHitComboWidget::UpdateComboCount(int32 Value)
{
  // only update if more than one hit
  if (TXTCombo && Value > 1)
  {
    if (TXTCombo->Visibility == ESlateVisibility::Hidden)
    {
      TXTCombo->SetVisibility(ESlateVisibility::Visible);
    }
    TXTCombo->SetText(FText::FromString((FString::FromInt(Value) + "x Combo")));

    if (ComboShakeAnimation)
    {
      PlayAnimation(ComboShakeAnimation, 0.f, 1, EUMGSequencePlayMode::Forward, 1.f);
    }

    if (ComboFadeAnimation)
    {
      PlayAnimation(ComboFadeAnimation, 0.f, 1, EUMGSequencePlayMode::Forward, 1.f);
    }
  }
}

In this method, we manipulate the state of the TXTCombo viability based on it being reset and set it back to visible.

We also take in the user provided combo count and add it to the text.

Once that is in place we play back the two animations, one to shake the text and the other to fade it away after a few seconds.

void UHitComboWidget::ResetCombo()
{
  GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Orange, __FUNCTION__);

  if (TXTCombo)
  {
    TXTCombo->SetVisibility(ESlateVisibility::Hidden);
  }
}

In this method we reset the visibility of the TXTCombo back to hidden.

void UHitComboWidget::StoreWidgetAnimations()
{
  AnimationsMap.Empty();

  UProperty* Prop = GetClass()->PropertyLink;

  // check each property of this class
  while (Prop)
  {
    // only evaluate object properties, skip rest
    if (Prop->GetClass() == UObjectProperty::StaticClass())
    {
      UObjectProperty* ObjProp = Cast<UObjectProperty>(Prop);

      // only get back properties that are of type widget animation
      if (ObjProp->PropertyClass == UWidgetAnimation::StaticClass())
      {
        UObject* Obj = ObjProp->GetObjectPropertyValue_InContainer(this);
        // only get back properties that are of type widget animation
        UWidgetAnimation* WidgetAnimation = Cast<UWidgetAnimation>(Obj);
        // if casting worked update map with new animation
        if (WidgetAnimation && WidgetAnimation->MovieScene)
        {
          FName AnimName = WidgetAnimation->MovieScene->GetFName();
          GEngine->AddOnScreenDebugMessage(-1, 4.5f, FColor::Magenta, AnimName.ToString());
          AnimationsMap.Add(AnimName, WidgetAnimation);
        }
      }
    }

    Prop = Prop->PropertyLinkNext;
  }
}

This is the big method that allows us to process each property of the current user widget and evaluate them for widget animations.

When a widget animation is found we update our private map with those details.

UWidgetAnimation* UHitComboWidget::GetAnimationByName(FName AnimationName) const
{
  UWidgetAnimation* const* WidgetAnimation = AnimationsMap.Find(AnimationName);
  if (WidgetAnimation)
  {
    return *WidgetAnimation;
  }
  return nullptr;
}

This method allows us to retrieve our animation by the keyed name.

In addition to the video here is a bunch of additional reading material:

Unreal Engine C++ Fundamentals – LineTraceSingleByChannel and friends ( DrawDebugBox, DrawDebugLine, FHitResult and VRandCone )

By | Development, Tutorial, Unreal | 9 Comments

Hey guys,

Back to fundamentals with LineTraceSingleByChannel and a bunch of other little methods that go, oh so well, with line traces.

First thing’s first, what is LineTraceSingleByChannel ?

Trace a ray against the world using a specific channel and return the first blocking hit … straight out of the documentation.

If that is not clear enough perhaps this picture can illustrate roughly what a line trace does. Let’s break it down:

  • So the line trace in our case is the stick
  • The start point of the line trace in the world is the bottom right hand corner where someone is holding it
  • The end or the destination of the line trace is Ned Flanders’s eye.
  • Cool.

Now what can we do with line traces ?

Turns out a bunch of stuff.

We can use them to determine where objects are in space relative to us.

For example, in the picture above, the game creator is sending a line trace from the GetRightVector and GetForwardVector location and based on the collision of those hits.

He can then determine the next move for the tile based character component.

He is also determining if the line trace is interacting with any static meshes and if that occurs he shoots out another line trace now parallel to the characters forward vector whatever the remainder of the length of the trace was.

So, all those games you enjoy playing, that are turn / tile based, can be very easily created using this technique !

 

Let’s take a look at the other example.

Here we can shoot a line trace against a component in order to determine if it can be destroyed.

We are going to do something similar to this example but don’t let my lack of imagination stop you from trying other wacky possibilities.

Ok let’s get to drawing some line traces and stop screwing around

 

A basic line trace needs a few components, let’s take a look at the code below.

float LineTraceDistance = 100.f;

FVector Start;
FVector End;

// get the camera view
FVector CameraLoc = FollowCamera->GetComponentLocation();
FRotator CameraRot = FollowCamera->GetComponentRotation();

Start = CameraLoc;

End = CameraLoc + (CameraRot.Vector() * LineTraceDistance);
  
// additional trace parameters
FCollisionQueryParams TraceParams(FName(TEXT("InteractTrace")), true, NULL);
TraceParams.bTraceComplex = true;
TraceParams.bReturnPhysicalMaterial = true;

//Re-initialize hit info
FHitResult HitDetails = FHitResult(ForceInit);

bool bIsHit = GetWorld()->LineTraceSingleByChannel(
  HitDetails,			// FHitResult object that will be populated with hit info
  Start,			// starting position
  End,				// end position
  ECC_GameTraceChannel3,	// collision channel - 3rd custom one
  TraceParams			// additional trace settings
);

if(bIsHit)
{
  // something was hit
}
else
{
  // we missed
}

Breaking it down we can see that the major parts are the start and end locations of where we want the line trace to travel to and from. We obtain those details from the players camera so, wherever our mouse is looking we will shoot out a line up to 100 units.

We can also see that we are going to use the third custom collision channel we created so whatever those settings connect with will be hit.

In addition we are passing in a few line trace parameters, specifically the following:

bTraceComplex – which tells us to use complex collision on whatever we interact with to provide better precision.

bReturnPhysicalMaterial – which tells us to provide details about the physical material, if one exists on the thing we hit, to come back in our hit result.

Lastly we can see that the result of the hit interaction goes into the FHitResult struct from which we can examine various bits of information about what we hit.

You holdin’ FHitResult ?

There are various bits of data we can get back from each hit result so let’s take a look at a few basic ones

if (bIsHit)
{
    Log(ELogLevel::WARNING, "We hit something");

    Log(ELogLevel::WARNING, HitDetails.Actor->GetName());
    Log(ELogLevel::DEBUG, FString::SanitizeFloat(HitDetails.Distance));
}

In this example we are simply printing out the name of the actor we hit as well as the distance between our point of origin and where the hit connected.

Based on those two details we already can do a bunch of stuff like cast the actor to the correct type and perform operations on him, like causing damage or displaying a menu or playing a sound.

Also based on the distance we can make certain assumptions, if the distance is greater than X perhaps our hit doesn’t generate damage or generates less damage due to distance. Or if the distance is too far we cannot interact with a certain lever in the game.

Lot’s of possibilities.

Great but I can’t see where I am aiming ?

No problem, we can drop in a few debug helpers to get us on our way. Specifically DrawDebugBox and DrawDebugLine which let us visualize in the world which way the line goes as well as where the hit occurs.

Here is the code snippet:

if (bIsHit)
{
  Log(ELogLevel::WARNING, "We hit something");
  // start to end, green, will lines always stay on, depth priority, thickness of line
  DrawDebugLine(GetWorld(), Start, End, FColor::Green, false, 5.f, ECC_WorldStatic, 1.f);

  Log(ELogLevel::WARNING, HitDetails.Actor->GetName());
  Log(ELogLevel::DEBUG, FString::SanitizeFloat(HitDetails.Distance));
  DrawDebugBox(GetWorld(), HitDetails.ImpactPoint, FVector(2.f, 2.f, 2.f), FColor::Blue, false, 5.f, ECC_WorldStatic, 1.f);
}
else
{
  Log(ELogLevel::WARNING, "Nothing was hit");
  // start to end, purple, will lines always stay on, depth priority, thickness of line
  DrawDebugLine(GetWorld(), Start, End, FColor::Purple, false, 5.f, ECC_WorldStatic, 1.f);
}

You can see that when we hit something we draw a green debug line and a debug box at the point of impact.

While when we miss we just draw a purple line all the way to the extend of our line trace.

Not bad, but make something interesting !

Ok fine, calm down ! We will make a shotgun spread using Math..s !

For this we are going to dive into the FMath library specifically VRandCone

// convert the degrees to radians
const float Spread = FMath::DegreesToRadians(LineTraceSpread * 0.5f);

FVector Start;
FVector End;

// convert the degrees to radians
const float Spread = FMath::DegreesToRadians(LineTraceSpread * 0.5f);

// get the camera view
FVector CameraLoc = FollowCamera->GetComponentLocation();
FRotator CameraRot = FollowCamera->GetComponentRotation();

Start = CameraLoc;

// handle spread
End = CameraLoc + FMath::VRandCone(CameraRot.Vector(), Spread, Spread) * LineTraceDistance;

Now with a bit of imagination we can take this bit of logic and turn it into a dangerous weapon, for example:

We build a weapon object of type shotgun

That object contains one to many shells in it’s magazine

When each shell is fired we generate 6 pellets

We then take our logic and loop over it 6 times using the direction of the weapon as our starting line traces and the weapons range as the end.

Boom !

Not something we will look at today but in the near future, I promise !

For more details check out the links below:

Unreal + Blender Tutorial – How to add root bones / motion or keep animations in place

By | Development, Tutorial, Unreal | No Comments

Hey guys,

Today we are going to roll into the New Year by adding in root motion to our kick animations as well as convert them to stay in place rather than move the mesh on their own.

This will help clean up the crappy roundhouse kick animation we had in place at the end of our last tutorial.

You can find the GitHub project in the usual location if you want to play with the finished animation sets.

Additionally here are a few links to do some further reading on the items we discussed:

Thanks and see you next time.