インターフェース

インターフェースの作成および実装に関するリファレンス

Choose your operating system:

Windows

macOS

Linux

Interface クラスは関連性のない一連のクラスが共通の関数を確実に実装するために役立ちます。これはあるゲーム機能が、それ以外は類似性がない大きく複雑なクラスによって共有される場合に非常に便利です。例えば、ゲームではトリガー ボリュームに入るとトラップがアクティベートし、敵が警戒したり、プレイヤーにポイントを報酬として与えるなどのシステムがあります。これはトラップ、敵、ポイント付与の "ReactToTrigger" 関数によって実装されることがあります。ただし、トラップは AActor`から、敵は特殊な APawn または ACharacter`サブクラスから、ポイント付与は UDataAsset から派生することがあります。こうしたクラスはすべて共有の機能を必要としますが、 UObject 以外は共通の 祖先 (ancestor) がありません。この場合、インターフェースをお勧めします。

インターフェースの宣言

インターフェース クラスの宣言は通常の Unreal クラスの宣言と似ていますが、大きな違いが 2 つあります。まず、インターフェース クラスは UCLASS マクロの代わりに UINTERFACE マクロを使用します。また、直接 UObject からではなく UInterface から継承します。

UINTERFACE([specifier, specifier, ...], [meta(key=value, key=value, ...)])
class UClassName : public UInterface
{
    GENERATED_BODY()
};

2 つめの違いは、UINTERFACE クラスは実際のインターフェースではありません。Unreal Engine のリフレクション システムで見えるようにするためにだけ存在する空のクラスです。他のクラスによって継承される実際のインターフェースは、必ず同じクラス名を持たなければなりませんが、イニシャルの "U" が "I" に変わっています。

ヘッダー ファイルで (例、 ReactToTriggerInterface.h ) 以下のようにします。

ReactToTriggerInterface.h

#pragma once

#include "ReactToTriggerInterface.generated.h"

UINTERFACE(MinimalAPI, Blueprintable)
class UReactToTriggerInterface : public UInterface
{
    GENERATED_BODY()
};

class IReactToTriggerInterface
{    
    GENERATED_BODY()

public:
    /** Add interface function declarations here */
};

"U プリフィックス" クラスはコンストラクタや他の関数を必要としません。"I プリフィックス" クラスはすべてのインターフェース関数を含み、他のクラスによって実際に継承されるものになります。

Blueprintable

インターフェース指定子

インターフェース指定子

意味

BlueprintType

ブループリントの変数に使用できるタイプとしてクラスを公開します。

DependsOn=(ClassName1, ClassName2, ...)

リストされている全クラスは、このクラスより前にコンパイルされます。ClassName は同じ (あるいは以前の) パッケージのクラスを指定しなければなりません。1 行の DependsOn をカンマで区切ったり、クラスごとに別の DependsOn 行を使うことで、複数の依存クラスを指定することができます。これは他のクラスで宣言された構造体や列挙型変数をクラスで使う場合に重要になります。コンパイラはクラス内のコンパイル済みのものしか認識しないからです。

MinimalAPI

他のモジュールで使用するために、クラスの型情報のみエクスポートさせます。クラスをキャストすることができますが、クラスの関数を呼び出すことはできません (インライン メソッドは除く)。そのため、他のモジュールからすべての関数にアクセス可能である必要のないクラスで何もかもをエクスポートしないことでコンパイル時間を短縮できます。

C++ でインターフェースを実装する

新規クラスでインターフェースを使用するには、"I プリフィックス" インターフェース クラスから継承します (使用している UObject ベースのクラスに加えて)。

Trap.h

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "ReactToTriggerInterface.h"
#include "Trap.generated.h"

UCLASS(Blueprintable, Category="MyGame")
class ATrap : public AActor, public IReactToTriggerInterface
{
    GENERATED_BODY()

public:
    /** Add interface function overrides here. */
}

インターフェース関数を宣言する

インターフェースで関数を宣言する方法は何種類かありますが、実装や呼び出しが可能な状況はそれぞれ異なります。すべての関数は先頭に「I」が付いたクラスでインターフェースに対して宣言し、外部クラスからも見えるように public にしなければなりません。

C++ インターフェースのみの関数

インターフェースのヘッダ ファイルで UFUNCTION 指定子を付けずに仮想 C++ 関数を宣言することができます。インターフェースを実装するクラスでオーバーライドできるように関数は仮想であってはいけません。

ReactToTrigger.h

public:
virtual bool ReactToTrigger();

ヘッダ内、またはインターフェースの .cpp ファイルのいずれかでデフォルト実装を指定できます。

ReactToTrigger.cpp

bool IReactToTriggerInterface::ReactToTrigger()
{
    return false;
}

Actor クラスでインターフェースを実装する場合、そのクラス固有のオーバーライドを作成して実装できます。

Trap.h

public:
virtual bool ReactToTrigger() override;

Trap.cpp

bool ATrap::ReactToTrigger()
{
    return false;
}

ただし、これらの C++ インターフェース関数はブループリントでは表示されません。

ブループリントでの呼び出しが可能なインターフェース関数

ブループリントでの呼び出しが可能なインターフェース関数を作成するには、 BlueprintCallable 指定子を使った関数の宣言で UFUNCTION マクロを指定しなければなりません。 BlueprintImplementableEvent 指定子、または BlueprintNativeEvent 指定子のいずれかを使用する必要があり、関数は仮想であってはなりません。

ReactToTrigger.h

public:
/**A version of React To Trigger that can be implemented in Blueprint only. */
UFUNCTION(BlueprintCallable, BlueprintImplementableEvent, Category=Trigger Reaction)
bool ReactToTrigger();

ReactToTrigger.h

public:
/**A version of React To Trigger that can be implemented in C++ or Blueprint. */
UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category=Trigger Reaction)
bool ReactToTrigger();

BlueprintCallable

BlueprintCallable 指定子を使った関数は、インターフェースを実装しているオブジェクトへの参照を使って C++ またはブループリントで呼び出すことができます。

BlueprintImplementableEvent

BlueprintImplementableEvent を使った関数は C++ でオーバーライドすることはできませんが、インターフェースを実装または継承しているブループリント クラスではオーバーライドが可能です。

BlueprintNativeEvent

BlueprintNativeEvent を使った関数は同じ名前の関数をオーバーライドすることで C++ で実装することができますが、末尾に _Implementation を追加します。

Trap.h

public:
bool ReactToTrigger_Implementation() override;

Trap.cpp

bool ATrap::ReactToTrigger_Implementation() const
{
    return false;
}

この指定子は実装をブループリントでオーバーライドすることも可能です。

任意のクラスがインターフェースを実装するかを判断する

インターフェースを実装する C++ と Blueprint のクラスの両方で互換性を得るためには、以下のいずれかの関数を使用します。

bool bIsImplemented = OriginalObject->GetClass()->ImplementsInterface(UReactToTriggerInterface::StaticClass()); // bIsImplemented will be true if OriginalObject implements UReactToTriggerInterface.

bIsImplemented = OriginalObject->Implements<UReactToTriggerInterface>(); // bIsImplemented will be true if OriginalObject implements UReactToTriggerInterfacce.

IReactToTriggerInterface* ReactingObjectA = Cast<IReactToTriggerInterface>(OriginalObject); // ReactingObject will be non-null if OriginalObject implements UReactToTriggerInterface.

StaticClass 関数が先頭に「I」の付くクラスで実装されていない場合、先頭に「U」の付くクラスで Cast の使用を試みるとすると失敗し、コードもコンパイルされません。

他の Unreal タイプにキャストする

Unreal Engine は、あるインターフェースから別のインターフェースへのキャスト、もしくはあるインターフェースからあるアンリアル タイプへのキャストを適宜サポートしています。

IReactToTriggerInterface* ReactingObject = Cast<IReactToTriggerInterface>(OriginalObject); // ReactingObject will be non-null if the interface is implemented. (インターフェースが実装されている場合は ReactingObject は null ではない)

ISomeOtherInterface* DifferentInterface = Cast<ISomeOtherInterface>(ReactingObject); // DifferentInterface will be non-null if ReactingObject is non-null and also implements ISomeOtherInterface.(ReactingObject が null でなく、かつ ISomeOtherInterface を実装する場合、DifferentInterface は null ではない)

AActor* Actor = Cast<AActor>(ReactingObject); // Actor will be non-null if ReactingObject is non-null and OriginalObject is an AActor or AActor-derived class.(ReactingObject is が null でなく、かつ OriginalObject が AActor もしくは AActor 派生クラスの場合、アクタは null ではない)

Blueprint Implementable クラス

ブループリントにこのインターフェースを実装させたい場合は、 Blueprintable のメタデータの指定子を使用しなければなりません。Blueprint クラスがオーバーライドしようとする関数は、 BlueprintNativeEvent または BlueprintImplementableEvent でなければなりません。 BlueprintCallable としてマークされる関数も呼び出し可能ですが、オーバーライドはされません。他のすべての関数はブループリントからアクセスできません。

Unreal Engine のドキュメントを改善するために協力をお願いします!どのような改善を望んでいるかご意見をお聞かせください。
調査に参加する
キャンセル