编写native code,在利用VS开始编译C++代码之前,利用Frontend进行脚本编译,有的脚本会自动生成一些native 类,除非我使用了noexport。
另外注意的地方是UE自己定义了一些宏,我将会总结这些宏的一般使用规律。
以《无尽之剑》的代码进行研究。通过这次研究使我掌握:
1.创建自己的native code
关注这些宏定义。为了让uc和C++能有交互,Epic定义了许多宏来解决问题。
先从《无尽之剑》的native code看起。
我们看到native代码并不多,我们的大多数工作内容都是使用unrealscript来实现逻辑的,方便快捷。只有在解决网络底层的时候我们再使用native code。
《无尽之剑》很好的使用包分类了自己的工程,包括UI,AnimNotifies,Inventory,kismet和Multiplayer,online 以及UI规划自己的uc脚本。
对于使用了native的uc,我们可以做一个测试进行编译。
第一个测试,创建自己的生成native脚本。我创建了一个ArtAnimNotify代码如下:
class ArtAnimNotify extends AnimNotify native(Anim); var bool bTestBool; //第一个测试变量 var() int bTestInt; //第二个测试变量 function int MyUCFunc(int a) { local int b; b=3; return a+b; } //native函数的定义区域 cpptext { virtual void testFunc1(); virtual FString testFunc2(int num); int MyNativeFunc(); }
简单说明:这段UC代码继承自AnimNotify,定义了自己的native代码名字Anim。
有一个Bool变量和一个int变量。开辟了一个C++代码区域,里面有两个函数。
对上述代码我在Frontend中进行脚本编译,然后在Inc头文件目录虚幻引擎自己生成了一个名为ArtGameAnimClasses.h的头文件,因为这是系统生成的,我抛去了自动生成的链接内容,这是帮助虚幻引擎和这些内容进行关联的:
在ArtGameAnimClasses.h中:
class UArtAnimNotify : public UAnimNotify { public: //## BEGIN PROPS ArtAnimNotify BITFIELD bTestBool:1; INT bTestInt; //## END PROPS ArtAnimNotify DECLARE_CLASS(UArtAnimNotify,UAnimNotify,0,ArtGame) virtual void testFunc1(); virtual FString testFunc2(int num); int MyNativeFunc(); };
我截取了一部分系统生成的核心代码,关联代码可以不管,系统会自动为我们生成。
对照着我们的UC代码我们可以看到变量部分:
var bool bTestBool; ----> BITFIELD bTestBool:1;
var() int bTestInt; -----> INT bTestInt; //注意C++无视我们可以在编辑器中可以编辑的()符号
而对于函数部分:
virtual void testFunc1();-------> virtual void testFunc1();
virtual FString testFunc2(int num)------> virtual FString testFunc2(int num);
int MyNativeFunc(); ---------> int MyNativeFunc();
可以看到,我写了什么就会输出什么,而这个cpptext就像一个类声明块。对于我没有在这个块中放的函数
function int MyUCFunc(int a);
你会发现头文件就不在具有了,系统会把这个当做一个单纯的UC函数来处理。
再者,我看到了头文件中有一个宏
DECLARE_CLASS(UArtAnimNotify,UAnimNotify,0,ArtGame);
这个宏的参数有当前的C++类,以及他的继承类UAnimNotify(从UC中和该头文件中可以看到继承关系)以及当前的工程名ArtGame。
2.多重头文件
我在《无尽之剑》中看到了有多个uc脚本都native(Anim)这个头文件,我很好奇这会是怎样的情况。因此我将进行这个步骤测试。
我定义了一个class ArtAnimNotify extends AnimNotify native(Anim);在这里没有定义cpptext区段
class ArtAnimNotify_FX extends AnimNotify native(Anim); /* cpptext { } */
因为我们在native(Anim),这个uc类会自动在头文件ArtGameAnimClasses.h中进行声明。
由于我们没有cpptext区段,系统会自动的加上没有定义构造函数。
class UArtAnimNotify_FX : public UAnimNotify { public: //## BEGIN PROPS ArtAnimNotify_FX //## END PROPS ArtAnimNotify_FX DECLARE_CLASS(UArtAnimNotify_FX,UAnimNotify,0,ArtGame) NO_DEFAULT_CONSTRUCTOR(UArtAnimNotify_FX) };
3.不标注Native(文件名)
我们在UC脚本中可以定义自己native和cpptext,编译过后系统为我们生成对应uc脚本的头文件。放在哪个文件中取决于native(文件名)
当然还有一种情况,你也可以不定义自己的文件名
class ArtAnimNotify_FX extends AnimNotify native;
这样的情况,头文件将会定义在ArtGameClasses.h中,也就是你的工程头文件中。
在下一节我将会进行基本的Native.cpp实现。