0:编写虚幻引擎中的UC和C++代码

Posted on 2016-02-26 14:48 neocsl 阅读(...) 评论(...) 编辑 收藏

  编写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代码如下:

 在ArtAnimNotify.uc中:
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实现。