从Unreal Engine 官方论坛上,看到了这篇关于C++接口方面的文章,感觉大家会在以后的UE4开发中会用到,为了让大家可以更熟练的去使用C++接口,下面就给大家介绍下关于在UE4 4.11+中C++ 使用接口的教程。
接口是不同的对象中拥有相同的函数,一般情况下,这些对象中的相同函数具有不同的功能。任何使用接口的类都必须实现这些接口。
这让你在写游戏中Actor的代码时更加的灵活方便。当你在C++和蓝图里可以触发事件,不同的Actor采用不同的方法来处理它们。
例如,本教程中实现像TimeBasedBehaviour这种类型的接口,它有一个ReactToHighNoon函数,并且有一堆Actor以不同的方式来响应这个函数。
又比如,继承自接口的Flower Actor覆写了其中的ReactToHighNoon方法,然后你可以创建一个事件比如SunReachedHighNon ,可以在任何一个可以获得Actor的地方触发这个事件(如关卡蓝图,Actor或静态蓝图库),检查Actor是否继承自接口,如果是继承自你需要的接口就可以调用该接口类中的所有函数,Actor将根据具体的实现和定义来执行不同的行为。
只要你有一个指向该对象的指针,调用时不需要知道它的具体类型。只要能成功将类型转换成接口类型的对象,你就可以调用此接口类定义下的接口函数了。
我们可以定义两种接口函数:一个是需要有c++默认实现的接口,标记为BlueprintNativeEvent(下面例子中的ReactToHighNoon()函数),以及一个不需要有默认实现的Blueprint Implement able Event(下面例子中的ReactToMidnight()函数)。
创建接口
以下是ReactsToTimeOfDay接口创建示例。
(如果希望将该接口当做事件,返回类型必须是void。如果你希望该函数能够在蓝图编辑器中被覆写,则必须具有非void的返回类型。)
Reacts To Time Of Day. h
05 | #include "ReactsToTimeOfDay.generated.h" |
09 | UINTERFACE(BlueprintType) |
10 | class MYPROJECT_API UReactsToTimeOfDay : public UInterface |
12 | GENERATED_UINTERFACE_BODY() |
15 | class MYPROJECT_API IReactsToTimeOfDay |
17 | GENERATED_IINTERFACE_BODY() |
21 | UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "MyCategory" ) |
22 | bool ReactToHighNoon(); |
25 | UFUNCTION(BlueprintImplementableEvent, BlueprintCallable, Category = "MyCategory" ) |
26 | bool ReactToMidnight(); |
ReactsToTimeOfDay.cpp
04 | #include "ReactsToTimeOfDay.h" |
06 | UReactsToTimeOfDay::UReactsToTimeOfDay( const class FObjectInitializer& ObjectInitializer) |
07 | : Super(ObjectInitializer) |
使用C++类中的接口
你需要使用多重继承,继承自我们创建的IReactsToTimeOfDay类。
第一个继承的类是你的基类,此处使用一个ASkeletalMeshActor作为示例。
Flower.h
02 | #include "ReactsToTimeOfDay.h" |
03 | #include "ASkeletalMeshActor.generated.h" |
06 | class AFlower : public ASkeletalMeshActor, public IReactsToTimeOfDay |
15 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "MyCategory" ) |
16 | bool ReactToHighNoon(); |
17 | virtual bool ReactToHighNoon_Implementation() override ; |
virtual bool ReactToHighNoon_Implementation()override;
这一行说明这个函数是从接口继承的。
UFUNCTION(BlueprintCallable,BlueprintNativeEvent,Category =“MyCategory”)
bool ReactToHighNoon();
说明你的类可以在蓝图中调用和覆写这个函数。BlueprintNativeEvents标记说明在蓝图中可以覆写这个C++函数。
注意:这里没有定义标记为BlueprintImplementableEvent的函数ReactToMidnight。 BlueprintImplementableEvent只需在我们的接口中声明,蓝图来具体实现他的功能。
Flower.cpp
03 | bool AFlower::ReactToHighNoon_Implementation() |
可以这样写来实现此接口
Frog.h
02 | #include "ReactsToTimeOfDay.h" |
03 | #include "AFrog.generated.h" |
06 | class AFrog : public ACharacter, public IReactsToTimeOfDay |
13 | UFUNCTION(BlueprintCallable, BlueprintNativeEvent, Category = "MyCategory" ) |
14 | bool ReactToHighNoon(); |
15 | virtual bool ReactToHighNoon_Implementation() override ; |
Frog.cpp
03 | bool AFrog::ReactToHighNoon_Implementation() |
确定一个Actor是否实现了想要的接口
要确定一个Actor是否在C++或蓝图中实现你想要的接口,只需将该对象转换为接口类的对象,如果返回NULL,则该对象并不具备你想要的接口。如果成功了,就可以使用转换过的指针调用接口函数了。
04 | UObject* pointerToAnyUObject; |
09 | IReactsToTimeOfDay* TheInterface = Cast(pointerToAnyUObject); |
15 | TheInterface->Execute_ReactToHighNoon (pointerToAnyUObject); |
16 | TheInterface->Execute_ReactToMidnight (pointerToAnyUObject); |
注意事项;
1.调用C++中的接口函数时,永远不要直接调用函数,使用带有Execute前缀的函数进行调用
2.你的函数必须具有返回值。如果你的函数返回void类型,UE4会将它当做一个事件,导致你不能覆写它(它不会出现在蓝图中的可覆写函数列表中)。如果你不需要一个返回值,就可以像上面的那样返回一个无用值。
Madgic接口
TheInterface-> Execute_ReactToHighNoon()
从上面的代码可以看出,这个函数是调用接口的,你甚至不需要知道对象的类型,只需要知道它是否支持你需要的接口。
根据实际的对象调用覆写后的函数产生不同的结果。这就是多态性。
在蓝图中覆写接口函数
按照上面说的做完后,C++中的接口函数将出现在蓝图里。
同样,接口函数必须具有返回值才能显示在此列表中,否则将被当做事件,不能被覆写。
你可以触发只有某些对象才会响应的全局事件,每个Actor都可以以自己独特的方式对事件做出回应。
虽然这个听起来比较复杂,但是它让代码在设计上更加简单,并且比使用不同的类具有更好性能!