Using the Interfaces in C++

Interfaces are super powerful tool and allows you to communitace easily between the C++ and Blueprints, even if the blueprint isn’t inherited from your custom C++ class! Also, Interfaces can be used to create the APIs that you can use with multiple projects.


Starting up!

To test this, we are simply starting a new C++ project based on the first person template. After the project is loaded, create a two class, both based on actors. Name name something like ClassA and ClassB or anything you want really. After that, create one more class that is based on ”Unreal Interface”. It should be one of the templates in the class creation screen. If not, just tick ”show all classes” and find it there.

 


 

Dwelving inside the code

We are going to create two interfaces, one that works both, in blueprints and in c++ and one that works only with C++. So go ahead, and open your interface header file. Inside header, you will find two classes combined inside this one. As the comments inside the class tells you. You don’t need to make any changes to the top one (class starting with the U)

Next, create a couple functions. C++ one is pure virtual and doesn’t need implementation. Blueprint ones needs, but leave it empty.

	// Blueprint version of interface, needs implementation in CPP
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Menu System")
	void BlueprintInterfaceFunction(); // This has empty implementation

	// Pure virtual virtuan function, used only in C++, doesn't need any implementation in c++
	virtual void NonBlueprintInterfaceFunction() = 0; 

Create implementation in CPP file

	void IMyInterface::BlueprintInterfaceFunction_Implementation()
{
}

Class B

Next, go to the class B Header file. We are going to implement our interface here and run our interface functions here. So inside header file, we need to kinda inherid this class from our interface. For that, you need to include our interface.h and add little code inside class creation section. For example in my class it could look this:

class COOPGAME_API AMyActor : public UActorComponent, public IMyInterface
{
GENERATED_BODY()
// Your header file code here.

}

Because we have inherited from the IMyInterface, we need to implement all the functions that are inside the Interface and this is why it’s so powerful. We KNOW, that we can safely call any interface function, because there has to be a function created for that, otherwise the compile will fail. So let’s create a two functions.

 // This is the blueprint version.
void BlueprintInterfaceFunction_Implementation();
 
// C++ Version
void NonBlueprintInterfaceFunction();

Add Implementation in CPP. We can try to log out or something. Leave the Blueprint empty, we are going to create logic inside blueprint in this one! You could of course use the C++ also

void AMyActor::BlueprintInterfaceFunction_Implementation()
{
}

void AMyActor::NonBlueprintInterfaceFunction()
{
UE_Log(LogTemp, Warning, TEXT("Interface function called"));
}

Our Class B is ready now. Remember, if you add new function to interface, you need to add them to all the classes inherited from Interface.

ClassA

We have Two ways to run the interface calls. One is to create a pointer object from our interface and run functions throug that, or use the Interfaces build-in function to run our custom functions. If we are doing, alter, we don’t need to alter the header file at all. But in this case, we are going to do both. So go to header file and include our interface. Note that you DON’T need to inherid this class from our interface. Don’t do that or you need to ass all the interface functions here, and we don’t need to do that. So just include our interface. Then inside public / private / protected (choose one) section create a Pointer object

IMyInterface* MyInterface;

Now, everything we need to do, is to call our interface functions. One way to call them was using the interface build-in, let’s do that first. Remember, that this is the same thing as calling any other function with a little exception: You need to add Execute_ before your function name. I do this in BeginPlay in this case.

void MyMyActor::BeginPlay()
{
IMyInterface::Execute_NonBlueprintInterfaceFunction(MYCLASSOBJECT));
}

Notice that in MYCLASS, we are going to tell in which class we are trying to send the message. If the class doesn’t implement the interface, nothing happens. This is perfectly crash-safe way to call functions. IF the MYCLASSOBJECT implements the Interface (like the ClassB did), it would run the NonBlueprintInterfaceFunction. Now here is where magic happens. You could have any class you ever want and if that implements the interface, it will surely run that function. In my case for example, I implemented interface inside the Blueprint Animation Graph. Then I just called it like this:

void MyMyActor::BeginPlay()
{
ICharMoveInterface::Execute_SetCrouchingAnimation(GetMesh()->GetAnimInstance(), MyPlayerState->CrouchingAnimation);
}

This way, I didn’t need to create a C++ version of the animation class, because interface doesn’t care where we are, it just runs if we are implementing it. Also notice, that there is a variable after the first parameters. This comes, if there is paremeters in your Interface function, they are seperated with comma. How this looks inside anim graph:

Now, we know that we can use the Execute_ , but what about the MyInterface object pointer? Well, it is up to you to fill it with the desired class. Notice that you can fill it with any class that implements the interface! So for example inside ClassB, when we got reference to our Class A (you would implement this in your game), we could do this:

ClassA->MyInterface = this;


It seems strange that IMyInterface* can take the class object inside it, but this would work because, the classB is deriving from our interface. Then, inside class A you could call functions through:

MyInterface->NonBlueprintInterfaceFunction();

Finally, if you create a Blueprint class from the class B, You can create a node from the BlueprintInterfaceFucnction, similary as seen in image above. To implement Interface inside blueprint, you would go Class Settings and just set the interface from there. If you already implemented interface through C++, it would how inside Inherited Interfaces.

 

That’s about it! This might seem complicated first, but just try and experience, you see that this is actually simple enough consept.

 

Vastaa

Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *