unreal是用反射_unreal 如何调用unreal studio - CSDN
  • 一、UE4中的反射系统 1.简述: 1.1 什么是UE4反射 在UE4里面,你无时无刻都会看到类似UFUNCTION()这样的宏。官方文档告诉你,只要在一个函数的前面加上这个宏,然后在括号里面加上BlueprintCallable就可以在编辑器...


    一、UE4中的反射系统


    1.简述:


    1.1 什么是UE4反射


    在UE4里面,你无时无刻都会看到类似UFUNCTION()这样的宏。官方文档告诉你,只要在一个函数的前面加上这个宏,然后在括号里面加上BlueprintCallable就可以在编辑器里面调用了。按照他的指示,我们就能让我们的函数实现各种各样特别的功能,那这个效果就是通过UE4的反射系统来实现的。这看起来确实非常棒,不过同时给UE4的反射系统增添了一点神秘感。我们可能一开始尝试着去找一下这个宏的定义,但是翻了几层发现没有头绪,可能也就懒得再去研究他是怎么实现的了。

    其实,所谓反射,是程序在运行时进行自检的一种能力,自检什么呢?我认为就是检查自己的C++类,函数,成员变量,结构体等等(对应起来也就是大家在UE4能看到的UCLASS,UFUNCTON,UPROPERTY,USTRUCT后面还会提到)。

    那检查这些东西做什么呢?最明显的就是支持蓝图和C++的交互功能,说的更通俗一点,就是可以更自由的控制这些结构,让他在我们想出现的地方出现,让他在我们想使用的地方使用。要知道我们在虚幻4中声明的任意一个类,都是继承于UObject类的,所以他远远不是我们所以为的那个普通的C++类。我们可以使用这个类进行网络复制,执行垃圾回收,让他和蓝图交互等等。而这一切原生的C++是并不支持的,也正是因此虚幻4才构建了一个这样的反射系统。


    1.2反射一般用于哪些地方


    在UE4里面, 基本上所有的游戏工程的类都需要用到。比如,你用编辑器新建一个类,类的前面会自动添加UCLASS();新建一个结构体,需要使用USTRUCT();新建一个枚举变量,需要在前面声明UENUM();在类的里面,也必须要加上GENERATED_UCLASS_BODY()才行。

    如果你想让你的变量能显示在编辑器里面,想让你的函数可以被蓝图调用或者通过让这个函数实现RPC网络通信功能,或者你想让你的变量被系统自动的回收,这些都离不开反射系统以及这些宏定义。

    所以,我们这里起码能认识到,在网络通信,蓝图交互以及垃圾回收方面,这与反射系统是密不可分的。

    另外,如果要说引擎中哪部分使用到反射系统功能的话,那基本上整个引擎都脱不了干系了。


    2.反射系统的基本原理:


    在了解反射系统前,我们必须要知道两个UE4独特的文件类型—“.generate.h”以及“.generate.cpp”。“.generate.h”文件在每一个类的声明前面都会被包含到对应的头文件里面。(这也是官方建议我们要用编辑器来创建类的原因,他们并不是常规的C++类)而“.generate.cpp”对于一整个项目只会有一个。这两种文件可以说是反射系统的关键所在,他们是通过Unreal Build Tool(UBT) 和UnrealHeaderTool(UHT)来生成的。

    补充:UnrealBuildTool(简称 UBT)是一个自定义工具,管理多个编译配置中的 虚幻引擎 4(UE4)源代码编译过程。

    UnrealHeaderTool(简称 UHT)是支持 UObject 系统的自定义解析和代码生成工具。代码编译在两个阶段中进行:1.HT 被调用。它将解析 C++ 头中引擎相关类元数据,并生成自定义代码,以实现诸多 UObject 相关的功能。2.普通 C++ 编译器被调用,以便对结果进行编译。)


    “.generate.h”与“.generate.cpp”文件都是做什么的?“.generate.h”与“.generate.cpp”文件里面都是什么?“.generate.h”里面是宏,而且包含一个非常庞大的宏,这个宏把所有和反射相关的方法(包括定义)和结构体连接到一起。而“.generate.cpp”里面是许多的函数定义,UnrealHeaderTool根据你在头文件里面使用的宏(UFUNCTION)自动的生成这个文件,所以这个文件并不需要你去修改,也不允许修改。UBT属性通过扫描头文件,记录任何至少有一个反射类型的头文件的模块。如果其中任意一个头文件从上一次编译起发生了变化,那么 UHT就会被调用来利用和更新反射数据。UHT分析头文件,创建一系列反射数据,并且生成包含反射数据的C++代码(也就是“.generate.cpp”)以及各种辅助函数与thunk函数(“.generate.h”)。


    这里简单举个例子,假如你有个类方法前面用宏定义(UFUNCTIONBlueprintNativeEvent)声明(BlueprintNativeEvent在ObjectBase.h中有定义,表示蓝图本地要实现的事件),你的cpp文件里面就不能去写这个函数的定义而是_ Implementation,因为UE4会认为你这个方法只想在蓝图实现,所以这个函数会在生成工具生成的过程中被定义在“.generate.cpp”里面,如果你在cpp定义就会提示编译错误(当然,因为你定义了两个一样的函数)。当你去调用这个函数的时候,首先会执行“.generate.cpp”里面的定义,之后会通过反射系统调用到蓝图。如果蓝图没有定义,那么最后会调用到GENERATED_UCLASS_BODY(后面会介绍这个宏)进而定位到.generate.h文件里面,最后执行“函数名_Implementation”,这也就是为什么要求我们在必须在.cpp声明为_ Implementation的原因。(该现象在4.9之前是经过验证的,不过最新版本的在写法上可能略有区别,等博主了解完新版本的区别后再做修改)


    3.反射系统的类型层次:


    按顺序依次是UField ,UStruct,UClass,UScriptStruct,UFunction,UEnum,Uproperty

    UStruct是所有聚合结构体的基础类型(包含其它成员的类型,比如一个C++类、结构体、或者函数),不应该跟C++中的结构体(struct)混为一谈(那是UScriptStruct)。UClass可以包含函数、属性以及它们的子类,而UFunction和UStriptStruct只能包含属性。

    你可以通过使用UTypeName::StaticClass()或者FTypeName::StaticStruct()来获取反射类型对应的UClass以及UScriptStruct,你也通过 一个UObject的实例通过Instance->GetClass()来获取类型(不能通过一个结构体实例的获取类型,因为结构体没有一个通用的基类或者需要的存储空间)。


    二、反射流程实例


    1.简述:

        

    前面简单描述了一个UFUNCTIONBlueprintNativeEvent的例子。这里我们以游戏中玩家使用道具的流程UFUNCTION(Reliable,Server) ServerRequestUseItem作为例子来解析一下反射的执行过程。首先需要知道的是,宏的UFUNCTION(Reliable,Server)意义。这是RPC通信,表示这个方法在客户端调用,服务器执行。而且我们在对应.cpp文件的函数实现必须要以“函数名_Implementation”来命名。   

           “工程名.generated.cpp”的文件一般位于“Project\工程名\Intermediate\Build\Win64\ Inc\工程名\工程名.generate.cpp”。

           “工程名.generated.h”的文件一般位于“Project\工程名\Intermediate\Build\Win64\ Inc\工程名\类名.generate.h”。


    2.流程描述:


    UE4Editor—ProjectName.dll! APlayerController::ServerRequestUseItem_Implementation(parameter1)
    UE4Editor—ProjectName.dll!APlayerController::execServerRequestUseItem_Implementation(FFrame&Stack,void*const Result)
    UE4Editor—CoreUObject.dll! UFunction::Invoke(Object*Obj,FFrame&Stack,void*const Result)
    UE4Editor—CoreUObject.dll! UObject::ProcessEvent(UFunction*Function,void* Parms)
    UE4Editor—Engine.dll! AActor::ProcessEvent(UFunction*Function,void* Parameters)
    UE4Editor—ProjectName.dll! APlayerController::ServerRequestUseItem (parameter1)
    UE4Editor—ProjectName.dll! APlayer::ClickItemUI ()
    ……..


     

    请参考上面这个代码执行栈来阅读下面的内容。UHT会给工程自动生成“工程名.generated.cpp ”的文件,里面包含了所有类的包含前置标记的的类方法,如网络通信UFUNCTION(Reliable,Server)以及C++和蓝图交互UFUNCTION(BlueprintNativeEvent)。因为我们在该类对应的.cpp文件只能声明_imlementation的函数,所以引擎在调用有这种标记的函数的时候,会执行以下的步骤。


             ①会去.generated.cpp去找函数的具体实现

             ②通过引擎工具自动生成的函数会调用位于“.generate.cpp”文件中的方法定义并执行

    ProcessEvent(FindFunctionChecked(SHOOTERGAME_ServerRequestUseItem),&Parms);接下来之所以会调用voidAActor::ProcessEvent(UFunction*Function,void*Parameters)。是因为一般的charactercontroller和pawn等实际存在于游戏中的实体都是继承自Actor的,所以他可以直接调用父类的ProcessEvent方法。

            ③由于AActor调用Super::ProcessEvent(Function,Parameters);所以会执行UObject的ProcessEvent,该函数的具体实现在ScriptCore.cppclassCOREUOBJECT_APIUObject : publicUObjectBaseUtilityUobject的具体实现分布在几个不同的文件里面,如obj.cpp、CoreUObjectPrivate.cpp等

            ④Uboject会调用Function->Invoke(this,NewStack,(uint8*)Parms +Function->ReturnValueOffset);NewStack是根据前面的Funtion参数创建的一个执行堆。

           ⑤在每个类的声明前我们都能看到UCLASS,这是UE4规定的格式。其实我们可以在看到对应类的.generated.cpp 文件中看到如下的宏定义。最后其实都是一些类与结构体的定义,


    #undef UCLASS
    #undef UINTERFACE
    #if UE_BUILD_DOCS
    #define UCLASS(…)
    #else
    #define UCLASS(…) \
    APlayerController_EVENTPARMS
    #endif
     
    #define APlayerController_EVENTPARMS\
    struct PlayerController_eventCheckCheatPassword_Parms\
    { \
        FString Pass;
    } \
    ……



    在类的定义的前面我们还会看到GENERATED_UCLASS_BODY()。这里的宏我们进一步展开,


    #undef GENERATED_UCLASS_BODY
    #undef GENERATED_INTERFACE_BODY
    #define GENERATED_UCLASS_BODY() \
    public: \
         APlayerController_RPC_WRAPPERS\
    APlayerController_CALLBACK_WRAPPERS\
    APlayerController_INCLASS \
    …
    DECLARE_FUCTION(execServerRequestUseItem)\
    {
    P_GET_OBJECT(UComponent,itemComp); \
    P_GET_STRUCT(struct FItemID,itemID); \
    P_FINISH; \
    this->ServerRequestUseItem_Implmentation(itemComp);
    }



    我们最后发现这个execServerRequestInventoryUseItem其实就是在GENERATED_UCLASS_BODY()定义的一个函数,在这里我们找到了ServerRequestUseItem_Implementation找到了也就是在.cpp文件服务器最终执行的函数。


    3.难点简述:

        

    在上面流程的第三步和第四步,涉及到了ProcessEvent和Invoke两个函数。这里面的机制比较复杂,整体来说是通过新建的结构体和代理来保存和传递函数指针。ProcessEvent会传递函数的名称以及参数,函数的地址与名称通过类UFuntion来保存,参数这回通过定义一个新的类来保存。然后将函数的名称与参数类的地址传递。要注意的是,在执行ProcessEvent(FindFuntionChecked(SHOOTERGAME_ServerRequestUseItem, &Params)的时候,FindFuntionChecked执行后所返回的UFuntion里包含一个成员函数指针,这个指针指向的就是execServerRequestUseItem。这些内容都是在UE4的编译工具编译时所产生的。

    4.综述:

          

    这个文档只是简单的从一个反射方法的实现流程上做了分析,而UE4的反射系统还是非常复杂和强大的。这里面涉及到宏的使用,蓝图系统,编译工具,成员函数指针以及一些特别的存储类,想完全理解这些可能需要非常长的时间,也确实比较难。我们平时写逻辑时也许根部不需要了解,但是对于一个程序员来说,理解总比不懂强,也许会给我们以后的设计增加一些灵感,有助于我们进一步理解UE4,以后如果有更深的理解会进一步完善这个博客的。


    参考文档链接:https://www.unrealengine.com/blog/unreal-property-system-reflection

    参考文档翻译链接:http://www.cnblogs.com/ghl_carmack/p/5698438.html#

     

    展开全文
  • 这篇博客讲解了在UE4中,反射机制的实现。

    这篇博客讲解了在UE4中,反射机制的实现。


    反射机制

    反射机制指的是程序可以在运行期间进行检测和修改自己状态的能力。

    UE4引擎使用C++语言编写,C++语言本质上不支持反射机制,但是UE4提供了反射机制的实现。

    FindFunction函数

    在UE4中提供了FindFunction函数,用于在UObject或者AActor中查找某个函数名的函数并且返回其函数指针。

    使用方法如下:

    UFunction *Injured = this->FindFunction(TEXT("Injured"));

    因此我们可以在Runtime时根据函数名的不同来进行函数的查找并且触发。

    使用ProcessEvent函数来进行函数的触发

    在UE4中提供了ProcessEvent函数来进行触发函数指针对应的函数,具体使用方法如下:

    UFunction *Injured = this->FindFunction(TEXT("Injured"));
    if (Injured)
    {
        ProcessEvent(Injured, nullptr);
    }

    ProcessEvent函数第一个参数是函数指针,第二个参数指的是参数列表,其类型为void*类型。

    使用CallFunction函数进行触发

    还可以使用CallFunction函数来进行对应函数的触发,但是需要进行FFrame的建立。

    并且为了避免内存泄漏,需要注意在使用过后销毁FFrame

    使用方法如下:

    UFunction *Injured = this->FindFunction(TEXT("Injured"));
    if (Injured)
    {
        void* params = nullptr;
        FFrame* frame = new Frame(this, Injured, params);
        CallFunction(*frame, params, Injured);
    
        delete frame;
    }

    额外功效

    使用如下的两种方法还可以有一个额外的功能 —— 在C++中进行BP函数的调用。当需要在C++与BP进行通信时,一个做法是在关卡中进行通信,另一个做法则是使用上面的方法进行函数调用。

    <全文完>

    展开全文
  • 介绍Unreal Engine 4与Unreal Engine 3的一些不同点。


    Unreal Engine 4发布好长好长时间了,直到最近才有时间仔细去看一下。

    TimSweeney老大一句话“IF YOU LOVE SOMETHING, SET IT FREE”,原来需要几十万授权金才能拿到的东西,就从$19,变成免费了,而且开源。作为一个国际顶尖的引擎,能走出这一步,对我等普通开发者真是福音啊。如此的牛X,再加上开源,相信Unreal Engine 4会火起来的,你看看最近E3上的产品展示也能感觉到。不过,Unreal的定位毕竟是“国际顶尖”,而非Unity3D那样的“开发大众化”,所以上手是有一定难度的。

    下面我把对Unreal Engine 4的初步印象总结一下,特别针对像我一样有Unreal Engine 3的同学,希望更多的同学来已经学习Unreal。


    UnrealScript去掉了

    开发语言上最大的变化,莫过于把UnrealScript去掉了。
    UnrealScript吧,当年来看还是一个非常NB的东西,要知道Unreal一代发布是1998年的事儿,而JAVA语言也就是95年才发布的。据说Tim Sweeney在开始设计Unreal的时候曾经考虑过使用Java作为上层语言,不过那时候Java还不成熟,所以他参考Java,实现了这个一个面向对象的,单根继承的脚本语言。不过,随着时间流转,Epic似乎并没有花太大的力气去演进UnrealScript。在Unreal Engine 3的时代,它确实显得有点老旧了,书写起来比一些现代语言确实有很多不方便的地方。所以,去掉就去掉吧。不过,值得注意的是,官方也留出了整合其他脚本语言的接口,例如LUA。


    C++11

    底层很多基础代码看上去有很强的亲切感,底层架构设计思路沿用了许多。底层依然是使用C++,不过用了很多C++11的特性,代码看上去简洁了不少。
    项目的编译、构建使用UnrealBuildTool,这应该是从3代延续过来;另外,就是增加了一个UnrealHeaderTool工具,猜想是根据UCLASS,UPROPERTY等宏,生成自定义反射信息用的,具体的还待进一步研究。


    Blueprint Visual Scripting

    据说这是UE4最牛X的改进了。看了看,原来是Kismet的延伸,连源代码很多都是UKismentXXX那一套。UE3里面的Kistmet只限于在一个关卡中使用,而Blueprint扩展了。关卡可以有唯一的一个Level Blueprint,相当于原来的Kismet;另外增加了Blueprint Class,大概就是用Blueprint创建自定义的Actor、Pown之类的,由于有了这个功能所以原来的Archetype顺带也就被替代了。其实,作为老一代屌丝Coder,我一直对Kismet那种表达式层级可视化编程,一直不太感冒(像Unity的PlayMaker那样,提供更高层级抽象的可视化工具更好)。不过,既然是UE4主推的个东东,还是得看看。
    不过,总体上给Designer一套可视化编程的东西,让他们自己实现一些关卡逻辑、游戏规则之类的,还真是一个特别好的方法。当然,我们这些Coder的工作还是不会丢掉的,例如游戏框架,游戏一些底层功能、常用模块还是要C++写好(或者使用LUA脚本?),封装给Blueprint来使用的。


    AnimTree哪去了

    UE3的AnimTree给我震撼太大了,所以特别关心UE4的动画系统。看了一下,貌似被分解成了BlendSpace和AnimGraph。
    • BlendSpace
      好比说“站立、走、跑”这三个动作,在UE3的AnimTree里面是有一个特定的node来混合的,根据移动速度不同。在UE4里,则需要创建一个BlendSpace1D资源,然后暴露出Speed参数。
    • AnimBlueprint
      使用Blueprint,AnimGraph,状态机等等控制角色的动画,怎么看上去和Unity的Mecanim有点像呢,唉~
    看来AnimTree是真的不见了,很遗憾,因为我觉得那个使用树形结构来抽象的动画系统,实在是非常清晰而且强大。

    渲染系统

    基于物理的渲染(PBR:Physically-Based Rendering)效果真的是太NB了,Unity5虽然也是PBR,好像比UE4还是略逊一筹啊!这个无需多言了,各种DEMO视频大家都看了不少了。渲染流程也完全走延迟渲染了。但多线程渲染,SceneProxy、Material之类的基础架构没怎么变。

    Behavior Tree

    这个东西好像在国外的游戏AI领域这几年挺流行了,是个很高大上的东西,UE4直接做了,太好了。

    另外,还有很多重大改进,例如Package,资源导入,增加插件支持等,这里就不一一细说了。推荐看一下官网的文章吧,作为本文的补充偷笑

    展开全文
  • unreal 的初步认识

    2017-08-17 13:07:54
    游戏结构先说怎么多 ,我们来玩玩引擎把,先来来说一说一个普通虚幻游戏的框架吧(好对照着引擎说) 上图是我在ununreal 官网抓下来的。现在我们来梳理一遍。可以看见 一个游戏(Game)的核心是游戏模式(Game...

    游戏结构

    我们来玩玩引擎吧,先来来说一说一个普通虚幻游戏的框架吧(好对照着引擎说)
    这里写图片描述
    上图是我在ununreal 官网抓下来的。现在我们来梳理一遍。可以看见 一个游戏(Game)的核心是游戏模式(GameMode)和游戏状态(GameState)。他们决定了游戏怎么玩(准确说怎么结束)。之后我们看见他把一个玩家控制器(PlayController) 加入(join)进去了,而这个控制器他控制(possess)着Pawn(不知道怎么翻译,暂且认为旗子吧)。而这个Pawn也可能是有AI控制器控制着(AIController)。再来看看玩家控制器中还有一个包含(Contains)这玩家界面(HUD),输入(input),玩家相机管理器(PlayerCameraManger)。

    引擎的初步认识

    这里写图片描述
    Viewport
    上图红色区域叫做Viewport,他实时显示着我们的游戏世界,一下是操作,请自己试试

    • 鼠标左,右键的拖拽和两个键一起拖拽
    • 像上面那样按住鼠标按键之后我们可以按q,w,e,a,s,d,z,,c建
    • alt 建+鼠标左,右键拖拽
    • 鼠标左键选择好ViewPort中的物体之后按F键会把窗口聚焦到该物体上。

    World Outliner
    绿色的World Outliner ,显示这我们游戏世界(Viewport)中所有的东西,无论是看得见还是看不见。

    Content Browser
    黄色区域Content Browser对应这游戏工程在硬盘中的Content文件夹下的文件结构。file->open project->右键某个工程->show in explorer

    modes
    蓝色modes 窗口,是一些预设的东西,你可以把想要的东西拖拽到ViewPort中,这样World outliner中也会出现该东西。

    Details
    其实右下角还有一个窗口 Details ,当你在在world outliner 或者Viewport中选择了相应的东西之后,Details 就会显示该物件的详细信息,因为我们没有选择任何东西,所以上图时空的。

    tips:
    如果你不小心把上面的窗口给关闭了,可以在左上角菜单栏window中找到所有窗口

    我们都知道unreal engine 是用c++最为开发语言的,而c++虽然很强大,但是因为c++编译语言的特性导致一些开发效率上的问题。所以epic 在开发unreal 的时候给他开发了很多有用的工具可以解放很多生产力。而这些工具放心使用的前提是你要遵守unreal 代码的书写规范。我会在以后陆续归纳其中的规则。

    类命名前缀

    虚幻引擎为您提供在构建过程中生成代码的工具。这些工具的使用必须遵循一些类命名规则。如命名与规则不符,将触发警告或错误。下方的类前缀列表说明了命名的规则。

    派生自 Actor 的类前缀为 A,如 AController。
    派生自 对象 的类前缀为 U,如 UComponent。
    枚举 的前缀为 E,如 EFortificationType。
    接口 类的前缀通常为 I,如 IAbilitySystemInterface。
    模板 类的前缀为 T,如 TArray。
    派生自 SWidget(Slate UI)的类前缀为 S,如 SButton。
    其余类的前缀均为 字母 F ,如 FVector。(为什么以F开头 官方给了链接

    UObject和AActor

    UObject和AActorn的是c++类名,名字遵循之前讲的类命名前缀
    UObject很像java 中的Object类,是Unreal engine 中绝大数类的父类,然而UObject类还不是根类,他”上面“还有 UObjectBaseUtility, UObjectBaseUtility”上面“还有UObjectBase。但是相对于UObjcet的父类来说,UObject是Unreal engine 最小的 ”单位“了,就像细胞内部其实还有东西,但是相对于人体来说我们可以把细胞看成最小的单位。这样你说你可能还是觉得有点抽象,那么我们来看看作为最为最小”单位“UObject能完成什么工作吧。(官方给的)

    • 垃圾回收
    • 引用更新
    • 映象
    • 序列化
    • 默认属性变化自动更新
    • 自动属性初始化
    • 自动编辑器整合
    • 运行时类型信息可用
    • 网络复制

    你可能不知道上面各项具体意思,没关系我也不知道。但是我们可以知道,官方认为上面的功能是Unreal engine 中每一个“东西”都可以有,但是不一定有的,所以就把这些功能写在了UObject类中了。

    现在来看看AActor。字面意思“演员”,但是不要被它迷惑,其实它是能被放入游戏世界场景的所有游戏性对象的基础类(不论能不能看见)。其实官方给了一个更好的解释,“AActor是一堆UActorComponent的容器” 现在你可能不知道什么是UActorComponent,没关系以后你自然会知道。还有一点很重要AActor继承自UObject,所以一个AActor也是一个UObject。

    知道这些之后我们就可以在来玩一玩unreal了。下面其实是一个官方案例,我觉得很不错就拿他来说一说了(其实就是懒)

    首先我们要新建一个AActor,
    在content Browser 中-> Add New->New C++ Class
    这里写图片描述
    然后你会看见Actor,注意不是AActor,为什么会这样呢,因为unreal 在设计时就定了一个小目标,那就是无论你是不是程序员都可以来开发游戏,
    所以写程序的人和设计游戏的人工作环境时相互独立的(visual studio 和unreal engine),程序员在visual studio 写的代码必须遵循之前所说的类命名前缀,之后官方开发的”小“工具就会把这些类的名字前缀在unreal engine中给屏蔽掉,所以设计人员在unreal engine 中看见的都是没有类命名前缀的代码。事实上官方为了设计分离还做了一个叫做blueprint的东西,
    好了回到之前的话题,选择它在选择Next,之后就是起名,我就起一个”FloatingActor“,路径就不要碰了(除非用文件夹分类)。不然会出现意想不到的错误(比如 ,必须在Source目录下才能存储我们创建的类)。然后 Create Class。之后会出现自动启动Visual studio 。
    tips:
    如果你 因为不可抗逆原因打不开的话,你可以unreal工程文件夹下,有一个以你工程名命名.sln结尾的文件,用visual studio 点开它 然后在Games-> Source->工程名 ,也会出现你AActor

    这里写图片描述

    Hot Reloading

    现在来说一说Hot Reloading 。这是个什么东西呢。我们都知道c++是一个需要编译的语言,解决方案分为两个你部分一个Engine,一个Game。Engine就是我们的unreal engine的本体了,也就是我们之前的操作界面,当我们编译运行上面代码时,会把unreal 引擎和我们的游戏代码一起编译运行(不信你可以试试)那么问题就来了,如果每一次我们修改代码都要编译一次。我的天,那么每一次都要关掉之前的界面,在打开编译的界面。于是hot reloading技术就诞生了。在unreal界面仍在运行时直接以普通方式从 Visual Studio 或 Xcode 进行编译。unreal 界面将检测到新编译的 DLL 文件是否修改并即时重载变更!当我们修改完代码我们可以
    这里写图片描述
    然后就出现
    这里写图片描述
    这样我们的unreal 就会自动更新我们编译之后的代码了
    或者
    这里写图片描述
    也可以完成上面的效果

    回到之前,我们创建完floatingActor 我们就会在unreal 的content browser中看见
    这里写图片描述

    unreal property system (reflection)

    接着我们回到visual studio中,先看我们

    //防止多次include 
    #pragma once
    //AActor定义在一下头文件中,看起来像文件夹结果,其实就是
    #include "GameFramework/Actor.h"
    //很重要单独说
    #include "FloatingActor.generated.h"
    //很重要单独说
    UCLASS()
    class STUDY_API AFloatingActor : public AActor
    {
    //很重要单独说
        GENERATED_BODY()
    
    public: 
        // Sets default values for this actor's properties
        AFloatingActor();
    
    protected:
        // Called when the game starts or when spawned
        virtual void BeginPlay() override;
    
    public: 
        // Called every frame
        virtual void Tick(float DeltaTime) override;
    
    
    
    };
    

    学习过c++的人看见这个类,有一种似曾相识的感觉。但是又有一点不一样,因为这是编辑器给我自动生产的代码。很多代码的运转,都有底层的一些”小“工具(程序)来协同运转。而上面有很多代码都是写给这些“小”工具看的。下面我们一一道来。#include "FloatingActor.generated.h"这句预编译语句非常重要。想要解释我们必须知道一个叫做 unreal property system 又叫reflection,这个套系统为程序赋予运行时进行自我检查的能力。很像java 中的反射机制。翻译成大白话就是当我们的游戏程序跑起来的时候,让unreal知道类中都写了什么。当知道程序中写了什么之后。这写信息就可以被用于诸如 编辑器中的细节面板、序列化、垃圾回收、网络复制、以及蓝图与C++交互等功能。是不是很强大。上面你看见的宏 UCLASS(),GENERATED_BODY(),这些宏标记了需要反射的东信息,当我们编译上述源代码时,UnrealBuildTool工具就会调用UnrealHeaderTool工具,UnrealHeaderTool工具会生成一些代码,~.generated.h,~.generated.cpp就是其生成的代码,其中包含了实现反射的详细代码。在C++定义内部它还包含一个GENERATED_UCLASS_BODY()的宏。GENERATED_UCLASS_BODY() / GENERATED_USTRUCT_BODY()在需要反射的类或者结构体里面是必要的,因为它们会加入额外的函数和typedef到类的内部。这方面的内容有很多我暂时也不懂,不想因为这个打乱学习接着只能不求甚解了,以后遇到会接着说。
    参考:
    https://www.unrealengine.com/blog/unreal-property-system-reflection
    翻译:
    http://www.cnblogs.com/ghl_carmack/p/5698438.html

    BeginPlay(),Tick(float DeltaTime)

    可以看见自动生成的代码覆盖了两个方法,BeginPlay()是一个事件,将告知您 Actor 已以可操作状态进入游戏中。现在便适合开始类的游戏性逻辑。Tick() 每帧调用一次,参数对应的时间量为自上次调用传入的实际运算时间。在此可创建反复逻辑。

    现在我们来看看源代码

    // Fill out your copyright notice in the Description page of Project Settings.
    
    #include "Study.h"
    #include "FloatingActor.h"
    
    
    // Sets default values
    AFloatingActor::AFloatingActor()
    {
        // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
        PrimaryActorTick.bCanEverTick = true;
    
    }
    
    // Called when the game starts or when spawned
    void AFloatingActor::BeginPlay()
    {
        Super::BeginPlay();
    
    }
    
    // Called every frame
    void AFloatingActor::Tick(float DeltaTime)
    {
        Super::Tick(DeltaTime);
    
    }
    

    对于以项目名命名的头文件Study.h大家可以先忽略,如果像了解可以参考下面链接
    参考
    http://www.cnblogs.com/wellbye/p/5837108.html

    这个类只有一个可以说的PrimaryActorTick.bCanEverTick = true;。设置这个参数之后,就会不间断调用Tick函数,如不需要此功能,最好将其移除(设置为false),以节约少量性能开销。如要移除此功能,必须将构建函数中说明 tick 应该发生的代码行删除。

    AActor在世界的表现

    现在我们会到unreal中,把我们创建FloatingActor拖到Viewport中
    这里写图片描述
    可以看见右边的world outliner中已经有我们的Actor,但是你在ViewPort中我们什么也看不见啊。先别急,我之前说过AActor是能被放入游戏世界场景的所有游戏性对象的基础类。但是还有一个更好的解释,**“一堆component的容器”现在就是你理解这句话的意思的最好时候,现在请安下面图片进行操作

    这里写图片描述

    这里写图片描述

    这里写图片描述

    这里写图片描述

    现在来你应该知道了,AActor派生的类其实就是一个容器,而UComponent派生的类就是真正的功能模块,对于component以后会说,现在有一个了解就可以了。

    现在我们我们回到Visual studio ,在floatingActor.h中加入下代码

    ....
        float RunningTime;
    ....

    在floatingActor.cpp加入下面代码

    ...
    void AFloatingActor::Tick(float DeltaTime)
    {
            Super::Tick(DeltaTime);
    
            FVector NewLocation = GetActorLocation();
            float DeltaHeight = (FMath::Sin(RunningTime + DeltaTime) - FMath::Sin(RunningTime));
            NewLocation.Z += DeltaHeight * 20.0f;      //把高度以20的系数进行缩放
            RunningTime += DeltaTime;
            SetActorLocation(NewLocation);
    
    }
    ...

    然后像上面热重载章节所说的那样选择一种方法 来编译。之后点击ViewPort上面的Play 按钮浏览一下画面

    这里写图片描述

    Tips:
    shift+1或esc来退出

    展开全文
  • UE4中的反射机制

    2016-12-27 20:22:49
    原文地址:Unreal Property System (Reflection) Reflection is the ability of a program to examine itself at runtime. This is hugely useful and is a foundational technology of the Unreal engine, ...
  • UE4-(反射反射采集

    2020-05-09 14:58:37
    通常将屏幕空间反射反射捕获相结合,两者各有优缺点,结合使用是希望同个结合两者的优点来弥补缺点。 大多情况下使用球体反射采集: 效果:不管怎么移动相机位置,屏幕上都会有反射效果。 问题: 当反射...
  • UE4 中使用反射

    2019-05-27 10:31:14
    C++中没有反射,UE4的C++中支持部分反射,蓝图中支持部分反射 蓝图中SetTimerByFunctionName,填写其中的FunctionName即可调用 整理自翰者学院视频教程:https://www.hanzhe.com,第七章 ...
  • 接触UnrealEngine4大概有快两周了,从安装配置到编辑器的熟悉,再到官方实例的学习以及Blueprint的应用。从UE3的UnrealScript和各种classes到UE4现在的发开方式,昨天大概拟定了一个UE4引擎探究的计划,下周会围绕...
  • 接触UnrealEngine4大概有快两周了,从安装配置到编辑器的熟悉,再到官方实例的学习以及Blueprint的应用... 这几天再看UnrealEngine4的代码,在写代码的过程中有些注意事项跟大家分享一下,也算给自己做个记录C++使用
  • 使用UFunction CustomThunk函数方式,实现蓝图模板功能节点,用来处理任意类型的数组,并探索实现细节背后的蓝图机制。
  • 屏幕空间反射(Screen Space Reflection 即 SSR)效果默认启用,如果场景中没有更改其他反射条件的情况下,只能使用屏幕空间反射。 也就是物体材质粗糙度值比较小,物体表面光滑时,物体表面所造成的反射效果。 ...
  • 兰伯特光照模型,用于模拟纯粹光滑物体表面的漫反射,也叫理想光照模型,反射的光线是均匀的向四面八方散射。 具体的计算公式: 光照强度的变化由入射光线和物体表面法线的夹角决定。就是cosθ
  • 今年是第二次参加UnrealOpenDay活动,收获颇丰,也认识了很多业界大咖。这里稍微详细点的总结一下会议内容和参会心得。 首先是行程: 会议9点签到,9:45正式开始。地点和去年一样还是在宝华万豪酒店,位于上海马戏...
  • 反射光照模型是:在所有方向上反射的光照强度相等,光照射到物体表面上一部分会被吸收而另一部分在其他方向上散射。一个典型的漫反射表面是没有光泽的,而没有被照射的地方是黑色的。 下面显示了一个漫反射光照...
  • UE4 C++使用反射

    2017-02-16 16:33:45
    使用: UFunction *rightFunc = this->FindFunction(FName(TEXT("OnRightMousePressed")));  if (rightFunc)  ProcessEvent(rightFunc, nullptr); 蓝图直接使用蓝图对象根据方法名取得方法 注意:...
  • unreal4特性介绍

    2017-09-12 10:44:31
    原文地址: https://www.unrealengine.com/products/unreal-engine-4  unreal enginer介绍 我的UE4学习(一) 你曾想过连线的形式来编写程序么; 你曾想过通过编辑工具就可以来创建类,并在vs中...
1 2 3 4 5 ... 20
收藏数 1,269
精华内容 507
关键字:

unreal是用反射