UE4 C++ How to make Component with Billboard SubComponent

UE4 Blueprints makes it very easy to drag and drop objects onto each other, but sometimes you want everything already set up.

I’ve been working on a procedural level generation system, which is designer assisted. So blocks that will be assembled to build a level need to be marked up by the designer with locations to spawn items and other things.

Doing this in Blueprints is very easy, make a new Blueprint extending Actor, then press AddComponent, pick BillBoardComponent, set it’s Sprite in it’s details panel and you are done. But, it’s a Blueprint itself which means code that runs it will have to go looking for blueprint instances. Additionally, it gets messier when the Blueprint extends Blueprint Component, and then these need to be added to each block.

So, moving all this to C++.

The result will be that when the designer is modifying a Block they will press add component, and select the one they want directly, then position it.

BlockWithComponents

 

It actually is very simple, but because it wasn’t directly documented it took me a while to figure it out. Here’s the code.

This is the base header file:

#pragma once

#include "Components/ActorComponent.h"
#include "Components/SceneComponent.h"
#include "Components/BillboardComponent.h"
#include "MarkerComp.generated.h"
UCLASS(Blueprintable, ClassGroup = (Marker), meta = (BlueprintSpawnableComponent))
class MYGAME_API UMarkerComp : public USceneComponent
{
GENERATED_BODY()

protected:
//A UBillboardComponent to hold Icon sprite
class UBillboardComponent* BillboardComponent;
//Sprite for the Billboard Component
class UTexture2D* SpriteTexture;

public:
// Sets default values for this component's properties
UMarkerComp(const FObjectInitializer& ObjectInitializer);

// Begin ActorComponent interface
virtual void OnRegister() override;

// Called when the game starts
virtual void InitializeComponent() override;

// Called every frame
virtual void TickComponent( float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction ) override;
};

I didn’t actually choose to make the Billboards in it’s .cpp, but in it’s derived classes. I use multiple because each type of marker in my system has different variables that need to be set as well as functions that will be called as the level is being generated, so it is more than just a different sprite.

#include "MyGame.h"
#include "MarkerComp.h"


// Sets default values for this component's properties
UMarkerComp::UMarkerComp(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	bWantsInitializeComponent = true;
	PrimaryComponentTick.bCanEverTick = true;

	//IconPath = "/Game/Lemons/Procedural/Blocks/Blueprints/icons/AmmoMarker";
	bVisualizeComponent = true;
}


void UMarkerComp::OnRegister()
{
	// If we need to perform a call to AttachTo, do that now
	// At this point scene component still has no any state (rendering, physics),
	// so this call will just add this component to an AttachChildren array of a the Parent component
	AttachTo(AttachParent, AttachSocketName);
	Super::OnRegister();
}

Here is the extending header.

#pragma once

#include "Components/ActorComponent.h"
#include "MarkerComp.h"
#include "AmmoMarker.generated.h"

UCLASS(ClassGroup = (Lemon), meta = (BlueprintSpawnableComponent))
class MYGAME_API UAmmoMarker : public UMarkerComp
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	UAmmoMarker(const FObjectInitializer& ObjectInitializer);

	// Called when the game starts
	virtual void InitializeComponent() override;

	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) override;
	
	
};

Here is the .cpp of an extending class that actually makes the Billboard Component.

#include "MyGame.h"
#include "AmmoMarker.h"


// Sets default values
UAmmoMarker::UAmmoMarker(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	bWantsInitializeComponent = true;
	PrimaryComponentTick.bCanEverTick = true;

	// Structure to hold one-time initialization
	struct FConstructorStatics
	{
		// A helper class object we use to find target UTexture2D object in resource package
		ConstructorHelpers::FObjectFinderOptional<UTexture2D> MarkerTextureObject;

		// Icon sprite category name
		FName ID_CatagoryName;

		// Icon sprite display name
		FText NAME_DisplayName;

		FConstructorStatics()
			// Use helper class object to find the texture
			// "/Engine/EditorResources/S_Note" is resource path
			: MarkerTextureObject(TEXT("/Game/Lemons/Procedural/Blocks/Blueprints/icons/AmmoMarker"))
			, ID_CatagoryName(TEXT("Marker"))
			, NAME_DisplayName(NSLOCTEXT("SpriteCategory", "AmmoMarker", "AmmoMarker"))
		{
		}
	};
	static FConstructorStatics ConstructorStatics;

	BillboardComponent = ObjectInitializer.CreateEditorOnlyDefaultSubobject<UBillboardComponent>(this, TEXT("Billboard"), true);

	SpriteTexture = ConstructorStatics.MarkerTextureObject.Get();
	BillboardComponent->Sprite = SpriteTexture;

	BillboardComponent->AttachTo(this);
}
Share Button

How to convert a UE4 Blueprints project to C++ Part 1

Blueprints are the Visual Scripting Language in UE4 and a large portion of the C++ API is available in them. Starting out a new project its always nice to get the basic mechanics on the screen as fast as possible and Blueprints are great for this.

But…

There are considerations besides performance of why you would want to use C++ in Unreal Engine 4.

If the purpose of Blueprints is to make things easier, but something would be easier to do in text, then that is where it should be done. They both have there place.

The real reason I like using Blueprints is because of how I can add and configure game objects in the Editor to it, and then directly use those objects on it’s Event Graph. In C++ there is more overhead in setting up components, and you can’t adjust things like offsets visually.

But, when it comes to sorting, searching and acting on collections Blueprints are a real pain. If I have a collection of  BaseClass variable in Blueprints, and want to do something different on each subclass in it, there is going to be a large spaghetti of repetitive Blueprints Nodes, getting the Class, comparing it etc.

SpawnActorsFromClassBP

So, the natural thing is to add C++ to the previously Blueprint only project. Actually adding it is very easy, just right click in the Content Browser and select add C++ class, choose a Base and name it. It’s that easy if you have set up Visual Studio.

But, where do you get started if you’ve only been programming with Blueprints in UE4?

I am going to list out some examples that should help speed you up, they are the things I had to hunt down, so I put them in one place here. This is as of 4.7, run from the launcher, adding C++ to a previously Blueprint Only project.

  • Spawn a Blueprint from C++
  • Get the components set in a Blueprint in C++,
  • Workflow for making new UE4 classes
  • Spawn Actor with AI in C++

 

Share Button

How to make a Spider in UE4 Part 2

SpiderHitNormal

 

Picking up from Part 1 where we left the Spider able to detect what surface is in front and under itself.

The next step is to get the surface angle of the detected object. The main reason is we want this Spider to be able to navigate any landscape and level geometry made in the Editor, and not just geometry that has been marked up with special tags for querying.

The FHitResult contains the ImpactNormal. This is the Normal of the surface, regardless of the angle the trace intersected at.

I added another trace directly down so that a comparison could be done. The above screenshot shows the results of the traces. The Floor shows a Z value of 1, and the Wall shows a Y of -1.

The walls will have a non zero value in X or Y, and the floor and presumably ceiling will have a non zero value in Z. Testing just against if an X or Y would equal a -1 or 1 would mean the spider would only think it could go up perfectly orthogonal walls. But, just testing if Not Zero found hits everywhere.

if (HitNormal.Y <= -0.02 || HitNormal.Y >= 0.02 || HitNormal.X <= -0.02 || HitNormal.X >= 0.02)

I picked up some “principals” of good practice that I try to adhere to when programming. One of them is not to use “Magic Variables”. In the above test 0,02 is a magic variable. I’ll change it out for a named one; maybe, “WallTestThreshold”.

 

Now that the Spider can tell when it can transfer to a wall, the next step is to actually transfer it.

ICanWallWalk

 

Share Button

How to make masked shape Health Bar in UE4 / UMG

Unreal Engine 4 has a build in User Interface system called UMG. It is very easy to work with and contains some base components like a progress bar that a lot of games would use. But, how many times do you want your health bar to be a perfect rectangle?

While the UMG may not offer the solution on the surface it allows you to place images, and there’s no reason the image can’t be a dynamic material that accepts input.

Here’s a picture of the end result.

TODO#Pic Coming soon

 

 

As you can see, it’s a non-rectangular shape. It starts filled when at 100% health, and empties as health runs out. Simply from top to bottom 1 to 0.

I’ll show with pictures how I achieved this effect. This isn’t a from scratch tutorial and requires either previous knowledge of working with Blueprints and Materials in UE4, or for the information to be looked up along with it.

First you need your assets. I saved mine as flattened .png’s from Fireworks with a background set to transparent.

1. A mask of the shape you want to be filled / emptied.

2. An outline or border shape that will always be rendered.

3. A texture to be panned to be used for the fill and transparency.

The textures do not need to be square. The dimensions for my outline and fill mask shape where 424 wide and 512 height. For your fill texture, keep the same width but double the height.

YellowBar

A picture is worth a 1,000 words. This is what the fill texture should look like. The white portion will give a color, the black texture will be transparent.

First, in UE4 make a new Material. Here’s a screenshot of my completed material.

MaterialGraph

Here is a link to the documentation for Dynamic material from the best source: Instanced Materials

The 1st node is a Scaler Parameter that I named percent. This is fed a value between 1 and 0 as the game is playing.

The 2nd node is a Subtract, I subtract .5 from the Percent. It is because I needed an offset.

The 3rd node is the panning node. This takes in the y parameter from .5 to -.5 in my case, this pans the fill texture. From white while filled, to Black for transparent.

The 4th Node is a Texture Sample, set the fill texture in it.

Now, on it’s own this would be a rectangle, so the 5th node is a multipy, add another Texture sample and set it to your mask texture. The mask should be white where you want it to show, and black where you want it to be transparent.

You will notice that the Mask Texture is not panned at all, only the fill texture is panned.

Set the output of the material to be Masked for it’s blend mode.

From the Multiply Node, which has the Fill and Mask as input wire that to the Base Color and Opacity Mask of the Material Final inputs. For the actual color itself, I made a constant vector 3 and set it’s RGB values to a subdued yellow. Wire that color node to the Emissive Color. That’s it for the material, and that’s the hardest part to get right.

 

TODO#Pic Coming soon

Now, make a new UMG widget for your UI, or open your existing UI widget that this effect will be added to. The best documentation on this is here:

UMG UI Designer User Guide

I added 2 images and set their size to be the same as my textures. I renamed them so I could get there references easier. They will be on top of each other so you won’t actually be able to mouse select the fill material one, and you will need to be able to grab the reference to the image from the variables bar when on the event graph of the UMG widget.

Set the images to both textures. With the image widget highlighted, look in the Appearance section of the details panel and select your images.

On the outline set it’s ZOrder to 1, or a number higher than the fill image. This will keep the Outline on Top of the filled image in the UI.

Notice that I didn’t use the UMD progress bar widget. I tried that at first and had difficulty with getting it to use the dynamic texture correctly. I used a simple image widget instead.

There’s really only 1 more step, assuming your player has a GetHealth function that returns a percentage of it’s max health. The step is to update the Material with the health percentage to get it to pan the fill.

This is a function on the UMG blueprint. It get’s the PlayerController, cast’s it to my type, and then get’s the Health Percent from it which it returns. My PlayerController class updates the Health as a percentage each tick, so it’s always a current value.

GetHealthPercentFunc

 

 

This probably didn’t need to be it’s own function, but I’ve found it easier when working in Blueprints to keep everything broken down into small functons makes the whole thing a lot less confusing and easier to maintain and debug when something isn’t working right.

Here is a picture of the main EventGraph of the UMG Widget. Drag the fill image from the variable panel onto the grid to Get it’s reference. Make a Node, Get Dynamic Material, from the image reference, then from it make a node Set Scaler Parameter Value. In the name section write the same name that you named the Scalar Parameter in the Material, mine was Percent. Into the value, I drag off the function I showed above that get’s the PlayerController’s health as a percentage.

 

UMGEventGraph

 

And, that’s it. Now you have a health bar shaped exactly as you like it! You can ask questions in the comments. I’ll either try to answer them there, or update the post itself for clarity.

 

TODO#Pic Coming soon

Share Button

How to make a Spider in UE4 Part 1

Wall walking, ceiling walking, going around corners, etc.

This will blog my progress through doing this small project. It will primarily be done in C++ and I won’t go into details of making the model or animations, but I will show how I set those up once they have been imported into the Engine.

 

SimpleCast

 

For the spider to be able to walk up walls, transfer onto the ceiling, or even around corners on walls it needs to be able to detect when it can.

I choose to create Sockets on the skeleton and then get there location in C++ to perform traces.

SpiderSockets

 

In C++, get the location and then run traces from the Socket above, to the separate feelers in front, down and diagonal.

Note: I need to find a better syntax highlighter for WP, this is WP-Code-Highlight. Recommendations are welcome. The right arrows are inconsistent.

 

// Tick animations before physics.
if (CharacterOwner->GetMesh())
{
const FVector Start = CharacterOwner->GetMesh()->GetSocketLocation("DetectionSocket");

const FVector FLSocketLocation = CharacterOwner->GetMesh()->GetSocketLocation("FL");
const FVector RLSocketLocation = CharacterOwner->GetMesh()->GetSocketLocation("FR");

FHitResult HitDataFL(ForceInit);
FHitResult HitDataRL(ForceInit);

if (Trace(CharacterOwner, Start, FLSocketLocation, HitDataFL, ECollisionChannel::ECC_Pawn, false, true))
{
   //Print out the name of the traced actor
   if (HitDataFL.GetActor())
   {
            print(HitDataFL.GetActor()->GetName());
    }
}

if (Trace(CharacterOwner, Start, RLSocketLocation, HitDataRL, ECollisionChannel::ECC_Pawn, false, true))
{
   //Print out the name of the traced actor
   if (HitDataRL.GetActor())
   {
       print(HitDataRL.GetActor()->GetName());
   }
}

 

This will provide the actor under each hit. This method alone would require a naming scheme to be implemented in all the levels to actually use it, so it is just for debugging. We will test the angle on hits to determine whether it’s a transition and what type.

It can be seen in the below picture, how the right feeler detects a hit, and the left does not.

SpiderFeelers

 

In the next picture, if you look at the printed comments you can see that the floor and wall are detected separately.

SpiderWallFloorDetection

Share Button