查看: 618|回复: 8

介绍Unreal Engine 4中的接口(Interface)使用C++和蓝图

[复制链接]

1

主题

342

帖子

7万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
75866
发表于 2015-9-30 21:31:00 | 显示全部楼层 |阅读模式




这个教程是从UE4 Wiki上整理而来.
在C++中直接使用Interface大家应该很熟悉。只是简单先定义一个个有虚函数的基类,然后在子类中实现相应的虚函数。像这样的虚函数的基类一般概念上叫接口。那接下来看看UE4中怎样在C++中定义接口的。
.h
#pragma once#include TargetInterface.generated.h UINTERFACE(MinimalAPI)class UTargetInterface :  public UInterface{  GENERATED_UINTERFACE_BODY()}; class ITargetInterface{  GENERATED_IINTERFACE_BODY()public:  UFUNCTION(BlueprintImplementableEvent, meta=(FriendlyName = On Interact ))  void OnInteract(bool bNewOpen);  virtual float GetHealth(); };
.cpp
#include YourProject.h #include TargetInterface.h UTargetInterface::UTargetInterface(const FObjectInitializer ObjectInitializer)   : Super(ObjectInitializer){ }// Give GetHealth a default implementationfloat ITargetInterface::GetHealth(){  return 0.0f;}
首先定义一个UTargetInterface这个是给引擎内部模块用的,一般不会用到,但是要定义。
ITargetInterface是你要使用的类,你要声明的函数接口都放在这里面。如果是定义函数给C++用的,那么你就直接按标准的C++声明一个虚函数就OK了,然后你要实现这个接口的子类继承ITargetInterface实现GetHealth函数就可以了。如果是给Blueprint用的,就要在函数前一行声明的UFUNCTION内加上BlueprintImplementableEvent,这样蓝图就可以实现这个接口了,蓝图中就像普通事件一样实现。
.h
#pragma once#include GameFramework/Actor.h #include TargetInterface.h #include NPCActor.generated.h UCLASS()class MMWORLD_API NPCActor  : public AActor  , public ITargetInterface{  GENERATED_BODY()public:  AInteractiveTargetActor();  virtual float GetHealth() override;  protected:  float Health;};
.cpp
#include YourProject.h #include NPCActor.h NPCActor::NPCActor(){ Health = 100.0f;}float NPCActor::GetHealth(){ return Health;}
在C++代码中这样调用.如果是你知道Actor类的实际类型,直接调用就可以了。你不知道Actor的类型时候Interface才有实际的用处。
auto MyInterface = Cast ITargetInterface (ActorInstance);if (MyInterface){ float ActorHealth = MyInterface- GetHealth();}
但是这样的接口蓝图中是无法使用的,蓝图完全无法知道它的存在。你可以再用Blueprint Function Library的方式再包装一层,但是我觉得这不是很好。
在蓝图中实现Event接口:
之前的NPCActor因为已经继承了ITargetInterface所以,你在蓝图编辑器里可以直接实现OnInteract接口事件。
那如果你纯蓝图的Actor怎么办。
进入蓝图编辑点Class Settings
[url=][img=244,36]file:///C:/Users/HenryRead/AppData/Local/Temp/WindowsLiveWriter1286139640/supfilesFC83FB/3402568203_thumb[1].png[/img][/url]
在Interfaces面板点Add加入Target Interface就好了
[url=][img=244,72]file:///C:/Users/HenryRead/AppData/Local/Temp/WindowsLiveWriter1286139640/supfilesFC83FB/3523847589_thumb[13].png[/img][/url]
那怎调用这个蓝图实现的接口在C++里?
看下面的代码
if (ActorInstance- GetClass()- ImplementsInterface(ITargetInterface::StaticClass())){ITargetInterface::Execute_OnInteract(ActorInstance, true);}
ActorInstance- GetClass()- ImplementsInterface(ITargetInterface::StaticClass())) 是用来判断这个Actor是否实现了TargetInterface,不管是在蓝图还是C++中都可以正确的判断(但是只有BlueprintImplementableEvent和BlueprintNativeEvent(这个后面再介绍)的函数才可以被蓝图实现)。Execute_OnInteract执行蓝图事件,第一个参数是UObject对象(接口调用的执行目标对象),后面的参数就是OnInteract函数的参数。这个函数是UHT自动生成的。其实这个函数本质上就是调用的UObject的ProcessEvent,具体你可以看生成的代码。(你到这个目录下的文件看看就知道了,Yourproject\Intermediate\Build\Win64\Inc\Yourproject\Yourproject.generated.cpp,Yourproject是你的项目名称) 最后一个问题,那如果想要这个函数接口既可以被C++实现又要被Blueprint实现怎么办?
你只要简单的把BlueprintImplementableEvent改成BlueprintNativeEvent就可以了。
.h
#pragma once#include InteractionsInterface.generated.h UINTERFACE()class MMWORLD_API UInteractionsInterface : public UInterface{  GENERATED_UINTERFACE_BODY()};class MMWORLD_API IInteractionsInterface{  GENERATED_IINTERFACE_BODY()public:  UFUNCTION(BlueprintNativeEvent)  void SwitchTurned(bool bNewOnOrOff, int32 CustomParam);};
.cpp
#include MMWorld.h #include InteractionsInterface.h UInteractionsInterface::UInteractionsInterface(const FObjectInitializer ObjectInitializer)  : Super(ObjectInitializer){}
实现的Actor
.h
#pragma once#include GameFramework/Actor.h #include InteractionsInterface.h #include InteractiveTargetActor.generated.h UCLASS()class MMWORLD_API AInteractiveTargetActor  : public AActor  , public IInteractionsInterface{  GENERATED_BODY()public:  AInteractiveTargetActor();  virtual void SwitchTurned_Implementation(bool bNewOnOrOff, int32 CustomParam) override;  UFUNCTION(BlueprintImplementableEvent, Category = Interactive)  void SwitchAllTurnedOnOrOff(bool bOnOrOff);  UFUNCTION(BlueprintCallable, Category = Interactive)  bool IsSwitchTurned(int32 Index);  UFUNCTION(BlueprintCallable, Category = Interactive)  bool IsSwitchAllTurnedOn();  UFUNCTION(BlueprintCallable, Category = Interactive)  bool IsSwitchAllTurnedOff();protected:  UPROPERTY(EditAnywhere, BlueprintReadOnly, meta = (ClampMin = 1 , ClampMax = 32 , UIMin = 1 , UIMax = 32 ))  int32 NeedSwitchTurnedNum;  uint32 SwitchTurnedStates;};
SwitchTurned在C++中要实现的函数是virtual void SwitchTurned_Implementation(bool bNewOnOrOff, int32 CustomParam) override; (BlueprintNativeEvent的函数名字_Implementation)。这个函数也是UHT自动生成的。
如果是你在Blueprint中是实现了SwitchTurned接口,那么C++的实现就会被覆盖隐藏掉。
那如果你的蓝图又要掉用C++接口实现怎么办?
UE4中没有直接实现这样的机制。但是你可以把SwitchTurned_Implementation实现提取出来一个新函数,然后把这个函数定义成UFUNCTION(BlueprintCallable, Category = Interactive),然后在蓝图中调用这个函数就解决了。

好了就介绍到这里,第一次写关于UE4的东西,不对的地方希望大家指正。希望这个对你有帮助。
参考例子:
https://github.com/henrya2/MMWorld

参考文章:
Interfaces And Blueprints Interfaces in C++ Expose an interface to blueprint
回复

使用道具 举报

0

主题

838

帖子

2739

积分

vip会员

Rank: 1

积分
2739
发表于 2015-10-12 23:38:28 | 显示全部楼层
看看
回复 支持 反对

使用道具 举报

0

主题

860

帖子

2811

积分

vip会员

Rank: 1

积分
2811
发表于 2015-10-13 01:14:19 | 显示全部楼层
好东西  
回复 支持 反对

使用道具 举报

0

主题

868

帖子

2865

积分

vip会员

Rank: 1

积分
2865
发表于 2015-10-13 03:26:29 | 显示全部楼层
我开始考虑从google的影响了  
回复 支持 反对

使用道具 举报

0

主题

848

帖子

2827

积分

vip会员

Rank: 1

积分
2827
发表于 2015-10-13 03:44:10 | 显示全部楼层
我怎么说那   
回复 支持 反对

使用道具 举报

0

主题

861

帖子

2822

积分

vip会员

Rank: 1

积分
2822
发表于 2015-10-13 07:49:58 | 显示全部楼层
我来看看 谢谢  
回复 支持 反对

使用道具 举报

0

主题

895

帖子

2936

积分

vip会员

Rank: 1

积分
2936
发表于 2015-10-13 08:43:24 | 显示全部楼层
当你感到悲哀痛苦时,最好是去学些什么东西 学习会使你永远立于不败之地   
回复 支持 反对

使用道具 举报

0

主题

859

帖子

2849

积分

vip会员

Rank: 1

积分
2849
发表于 2015-10-13 16:39:31 | 显示全部楼层
勤奋真能造就财富吗?  
回复 支持 反对

使用道具 举报

0

主题

865

帖子

2831

积分

vip会员

Rank: 1

积分
2831
发表于 2015-10-13 16:41:34 | 显示全部楼层
沙发,板凳都没偶的份了   
回复 支持 反对

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | enginedx注册

本版积分规则

 
 



邮件留言:


 
返回顶部