unreal4入门系列之十一

2016-11-22 13:28:18 u013131744 阅读数 7037

193959y00hr0lcer20iljg

1) 进入虚幻4的官方主页(https://www.unrealengine.com/

这里你可以获得关于虚幻4的最新资讯,包括版本更新、博客更新、新闻和商城等。自2015年起,该引擎已经提供免费下载的服务。

除了UE4的官网主页,我也推荐你收藏如下网站:
2) 在官网主页,点击右上角的获得虚幻引擎。


3) 看到弹出一个登录界面,根据提示填写相关信息,然后勾选“我已经阅读并同意服务条款”,点击注册。然后登录进去。就会显示如下的界面,点击下载即可:


4) 下载并安装好后,打开桌面上的Epic Games Launcher图标。填写刚刚注册的帐号密码,点击登录。需要一定时间来启动,请稍等几分钟哦。


5) 登录后会看到如下图所示界面。然后点击“库”,再点击“添加版本”,你会看到最新版本的UE4。再点击“安装”,开始时需要等待几分钟,几分钟过后,程序会自动下载安装UE4。(注意,该步骤如果失败了可能需要翻墙)

6) 自动安装好后,点击左上角的“启动”。


7) 大功告成!

 


转自:http://www.52vr.com/article-553-1.html

2016-11-22 13:37:26 u013131744 阅读数 3585

201922rb1l3syoyu1glbys

当你运行我们上次做完的项目,你可能会意识到我们移动的摄像机还是默认的那个摄像机,这个默认的摄像机可以自由飞翔。这一节,我们要使得开始的角色是我们的一个Avatar类的实例对象,并且使用键盘控制我们的角色。

创建游戏模式类

1. 创建游戏模式的步骤如下:
1) 点击文件 --> 新建C++类。
2) 选择Game Mode(游戏模式)。
3) 将其命名为“MyGameMode1”。
4) 点击创建类。

什么是GameMode?GameMode包含了各种各样的游戏规则和让游戏引擎描述这个游戏是怎么玩的。

2. 创建游戏模式的蓝图
UE4会自动启动VS开发环境,然后我们来创建MyGameMode1蓝图:

1) 如图所示操作:

2) 填写蓝图名称,我这里是“BP_GameMode1”,然后点好。

3) 从右侧的细节面板中的Default Pawn Class的下拉选项中选择上次我们创建好的角色蓝图BP_Avatar。

什么是Default Pawn Class?Default Pawn Class就是被角色使用的那一类物体,也就是可以被玩家控制的Actor角色。

4) 点击工具栏的保存,然后退出。

现在运行游戏的话,你可以看到我们使用的摄像头已经是BP_Avatar角色所包含的摄像头了。但是现在还是控制不了角色,因为我们还没设置控制器输入。

设置检测键盘输入

1) 点击工具栏的设置,然后点击项目设置。


2) 接下来,点击左侧面板的输入,然后在Axis Mappings(按键映射)后面点击加号,再点击前面的小三角形展开。输入一个名为Forward(前进)的按键映射,然后下面选择W键。接着再添加一个名为Back(后退)的按键映射,然后下面选择D键。Left(左移)对应A键,Right(右移)对于D键。

3) 直接关闭该窗口以保存设置。

通过C++代码控制角色行走

1) 现在打开你的VS里面的Avatar.h构造器,添加五个成员函数的声明:
  1. //添加如下三个成员函数,用于角色控制:
  2. void SetupPlayerInputComponent(class UInputComponent* InputComponent) override; //覆写虚函数,当有输入的时候被调用以绑定功能
  3. void MoveForward(float amount);
  4. void MoveBack(float amount);
  5. void MoveLeft(float amount);
  6. void MoveRight(float amount);
并删除原有的这一行:
virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;

2) 然后在Avatar.cpp完成函数体定义:
  1. //游戏开始时被调用以绑定设备输入功能
  2. void AAvatar::SetupPlayerInputComponent(class UInputComponent* InputComponent)
  3. {
  4. check(InputComponent); //检查空指针
  5. InputComponent->BindAxis("Forward", this, &AAvatar::MoveForward);
  6. InputComponent->BindAxis("Back", this, &AAvatar::MoveForward);
  7. InputComponent->BindAxis("Left", this, &AAvatar::MoveRight);
  8. InputComponent->BindAxis("Right", this, &AAvatar::MoveRight);
  9. }
上面的InputComponent::BindAxis(...)函数用于将按键信息于函数调用绑定。例如当玩家按下W键,引擎就会检测到有我们之前命名的"Forward"按键信息,然后自动去调用当前类的AAvatar::MoveForward(float amount)函数。其它三个按键也是如此运作。所以接下来定义好这四个函数就可以了,这里的参数amount是设备输入量经过与scale相乘后得出的结果:
  1. void AAvatar::MoveForward(float amount)
  2. {
  3. // Controller控制器当前拥有该actor。例如如果当前角色死了,actor不存在了,此时Controller控制器没有拥有任何一个actor,那么如果我们还想去控制它,就会出错。
  4. // 如果控制器没有拥有actor或者移动量是0,不能进入该函数。
  5. if (Controller && amount)
  6. {
  7. // GetActorForwardVector()取得角色向前的向量
  8. FVector fwd = GetActorForwardVector();
  9. // 我们调用AddMovementInput来在‘fwd’向量的方向上移动角色‘amount’个单位
  10. AddMovementInput(fwd, amount);
  11. }
  12. }
  13. void AAvatar::MoveBack(float amount)
  14. {
  15. if (Controller && amount)
  16. {
  17. // GetActorForwardVector()取得角色向前的向量,加上负号,该向量就向后,所以取得了角色向后的向量
  18. FVector back = -GetActorForwardVector();
  19. AddMovementInput(back, amount);
  20. }
  21. }
  22. // 后面的函数类似前面,很容易懂
  23. void AAvatar::MoveLeft(float amount)
  24. {
  25. if (Controller && amount)
  26. {
  27. FVector left = -GetActorRightVector();
  28. AddMovementInput(left, amount);
  29. }
  30. }
  31. void AAvatar::MoveRight(float amount)
  32. {
  33. if (Controller && amount)
  34. {
  35. FVector right = GetActorRightVector();
  36. AddMovementInput(right, amount);
  37. }
  38. }

设置检测鼠标移动

接下来我们用第二步同样的操作打开项目设置并添加Yaw和Pitch按键信息,分别对应的是鼠标的X坐标和Y坐标。

注意Yaw的意思是绕竖轴旋转,Pitch的意思是绕横向轴旋转。见下图:

通过C++代码控制角色镜头

在Avatar.h你需要添加两个函数声明:
  1. void Yaw(float amount);
  2. void Pitch(float amount);
然后在Avatar.cpp中实现它们:
  1. void AAvatar::Yaw(float amount)
  2. {
  3. if (Controller && amount)
  4. {
  5. // AddControllerYawInput()函数用于改变控制器的Yaw变量,即增加纵向轴旋转量。
  6. // GetWorld()函数取得世界指针UWorld*,通过世界指针调用GetDeltaSeconds()取得每帧耗费的时间。
  7. // 之所以要乘以每帧耗费的时间,是为了使得每一【秒】都增加200.0f * amount的改变量。
  8. // 如果不乘以每帧耗费的时间,那么每一【帧】都会增加200.0f * amount的改变量。(注意由于每秒渲染量不同,所以每秒的帧数不一定是固定的。)
  9. // 通过帧数来控制变量,那么游戏看起来就不那么流畅。试想,机子性能好的时候游戏角色动作就迅速,机子性能差的时候游戏角色动作就慢,这对于玩家公平吗?
  10. AddControllerYawInput(200.f * amount * GetWorld()->GetDeltaSeconds());
  11. }
  12. }
  13. // 下面的函数与上面雷同,不再赘述
  14. void AAvatar::Pitch(float amount)
  15. {
  16. if (Controller && amount)
  17. {
  18. AddControllerPitchInput(200.f * amount * GetWorld()->GetDeltaSeconds());
  19. }
  20. }
在void AAvatar::SetupPlayerInputComponent(class UInputComponent* InputComponent)函数体的下面添加这两条语句将输入信息和函数绑定:
  1. InputComponent->BindAxis("Yaw", this, &AAvatar::Yaw);
  2. InputComponent->BindAxis("Pitch", this, &AAvatar::Pitch);

完整代码贴出

Avatar.h完整代码如下:
  1. #pragma once
  2. #include "GameFramework/Character.h"
  3. #include "Avatar.generated.h"
  4. UCLASS()
  5. class DEMO1_API AAvatar : public ACharacter
  6. {
  7. GENERATED_BODY()
  8. //添加如下五个成员函数,用于角色控制:
  9. void SetupPlayerInputComponent(class UInputComponent* InputComponent) override; //覆写,游戏开始时被调用以绑定设备输入功能
  10. void MoveForward(float amount);
  11. void MoveBack(float amount);
  12. void MoveLeft(float amount);
  13. void MoveRight(float amount);
  14. void Yaw(float amount);
  15. void Pitch(float amount);
  16. public:
  17. // 设置角色属性的默认值
  18. AAvatar();
  19. // 当游戏开始的时候被调用
  20. virtual void BeginPlay() override;
  21. // 每帧被调用
  22. virtual void Tick( float DeltaSeconds ) override;
  23. };

Avatar.cpp完整代码如下:
  1. #include "Demo1.h"
  2. #include "Avatar.h"
  3. // 设置默认值
  4. AAvatar::AAvatar()
  5. {
  6. // 设置这个角色每帧调用Tick()。 如果不需要的话你可以关掉它以提高性能。
  7. PrimaryActorTick.bCanEverTick = true;
  8. }
  9. // 当游戏开始时调用它
  10. void AAvatar::BeginPlay()
  11. {
  12. Super::BeginPlay();
  13. }
  14. // 每帧被调用
  15. void AAvatar::Tick( float DeltaTime )
  16. {
  17. Super::Tick( DeltaTime );
  18. }
  19. //游戏开始时被调用以绑定设备输入功能
  20. void AAvatar::SetupPlayerInputComponent(class UInputComponent* InputComponent)
  21. {
  22. check(InputComponent); //检查空指针
  23. InputComponent->BindAxis("Forward", this, &AAvatar::MoveForward);
  24. InputComponent->BindAxis("Back", this, &AAvatar::MoveForward);
  25. InputComponent->BindAxis("Left", this, &AAvatar::MoveRight);
  26. InputComponent->BindAxis("Right", this, &AAvatar::MoveRight);
  27. InputComponent->BindAxis("Yaw", this, &AAvatar::Yaw);
  28. InputComponent->BindAxis("Pitch", this, &AAvatar::Pitch);
  29. }
  30. void AAvatar::MoveForward(float amount)
  31. {
  32. // Controller控制器当前拥有该actor。例如如果当前角色死了,actor不存在了,此时Controller控制器没有拥有任何一个actor,那么如果我们还想去控制它,就会出错。
  33. // 如果控制器没有拥有actor或者移动量是0,不能进入该函数。
  34. if (Controller && amount)
  35. {
  36. // GetActorForwardVector()取得角色向前的向量
  37. FVector fwd = GetActorForwardVector();
  38. // 我们调用AddMovementInput来在‘fwd’向量的方向上移动角色‘amount’个单位
  39. AddMovementInput(fwd, amount);
  40. }
  41. }
  42. void AAvatar::MoveBack(float amount)
  43. {
  44. if (Controller && amount)
  45. {
  46. // GetActorForwardVector()取得角色向
转自:http://www.52vr.com/article-562-1.html



2015-07-16 10:16:38 pizi0475 阅读数 12827

http://blog.sina.com.cn/s/blog_7c5fd2e90101ku0j.html

使用Unreal4引擎前需要安装 或者编译引擎。 下面就为同学们介绍下 Unreal4 安装配置。


一. 在Win7下安装Unreal4

在Win7下安装Unreal4需要以下几个步骤:

1. 打开控制面板程序和功能 检查是否已安装 Microsoft Visual C++ 2010 Redistributable ,请同学们先卸载掉,否则下面安装DXSDK_Jun10时会出现Error Code:S1023错误。(卸载完成一定要重启电脑 不然还会出现Error Code:S1023的错误 如果没有安装的同学请继续下一步Unreal4 <wbr>入门(安装) 

Unreal4 <wbr>入门(安装)


2. 安装DXSDK_Jun10 如果出现下图所示错误Error Code:S1023 请先完成第一步。

Unreal4 <wbr>入门(安装)


3. Win7下还需要安装 Windows 7 SP1(Service Pack 1) KB976932 补丁(windows6.1-KB976932-X64.exe)补丁可以从微软上下载(大概903MB)
附下载地址(http://windows.microsoft.com/zh-cn/windows7/learn-how-to-install-windows-7-service-pack-1-sp1


4. 安装完Windows 7 SP1(Service Pack 1) KB976932 补丁后就接下需要安装10以上版本的InternetExplorer浏览器。大概就是ie11_windows6_1_x64_zh_cn.exe 的一个安装程序。
附下载地址 Internet Explorer 11(http://windows.microsoft.com/zh-cn/internet-explorer/ie-11-worldwide-languages


5. 以上4步完成后就可以安装高端大气上档次的VisualStudio2013,也可以选择安装VisualStudio2012看个人喜好但是VisualStudio2013是Unreal4Engine引擎开发IDE所以UE4对VS2013支持的最好,还有很多插件呦。


6. 最后一步就是安装UE4了,直接安装UnrealEngineInstaller-1.0.0-2039063.msi文件。桌面或者安装路径的Unreal Engine\Launcher\Engine\Binaries\Win64\UnrealEngineLauncher.exe 可以直接运行啦。

Unreal4 <wbr>入门(安装)


7. UnrealEngineLauncher是一个引擎用户验证登陆器,使用了增量更新机制(哈哈 做游戏的更新机制已经给大家展现出来,具体能有多强大还需要好好研究一下Unreal4 <wbr>入门(安装))。在(https://www.unrealengine.com/blog/welcome-to-unreal-engine-4)Unreal4官网注册一个账号就可以登录。
我在淘宝花了120大洋找人代付了1个月的会员,还购买了一个月的GreenVPN。准备好好研究下喽Unreal4 <wbr>入门(安装) 
会员登陆后还需要更新一个4.0.2的包大概7个G左右(嘿嘿 知道为什么买VPN了吗 - -!)

Unreal4 <wbr>入门(安装)


二. 在Win8/Win8.1 下安装Unreal4

1. 依然首要问题安装DXSDK_Jun10时会出现Error Code:S1023错误。只要按照Win7下安装的第一步解决就OK了,一定不要忘记卸载完要重新启动计算机呦。

2. 安装Visual Studio 2013或者Visual Studio 2012,个人建议选择VS2013许多新特性很适合Unreal4,而且UE4对Visual Studio 2013支持的比较好。
 
2. 就可以直接安装UnrealEngineInstaller-1.0.0-2039063.msi文件了。


三. 其他方式安装Unreal4 Engine

算是小福利喽,不想付费又对UE4感兴趣的同学可以看下面方法,但是不确保链接总是会有效喔。
Unreal4源码包下载链接(http://pan.baidu.com/s/1qWCYkz
引擎资源包(一)下载链接(http://pan.baidu.com/s/1eQzfwo
引擎资源包(二)下载链接(http://pan.baidu.com/s/1dD5Tcn

1. 下载好Unreal4源码后先将压缩包解压缩,得到UnrealEngine-4.0.1-release文件夹,然后需要把引擎资源包(一)和引擎资源包(二)下载后解压到UnrealEngine-4.0.1-release文件夹下覆盖相应目录文件。

2. 安装DXSDK_Jun10.exe,如果出现下图所示错误Error Code:S1023 请同学们看一下上面Win7安装Unreal4的第一步骤。

3. 安装完DXSDK后,双击UnrealEngine-4.0.1-release目录下的GenerateProjectFiles.bat文件,等待差不多1分钟后点击目录下的Ue4.SLN(VisualStudio2013的工程文件

4. 然后就可以用VisualStudio2013打开工程文件可以进行编译了,编译时间会很长根据每位同学机器配置会有差异基本上15分钟就可以搞定,请同学们耐心等待。编译完成后就可以在 \UnrealEngine\Engine\Binaries\Win64目录找到UE4Editor.exe等运行文件啦。


小结:官方说现在还是未优化版本,稳定版请等待几个月会推出4.1版本(版本更新说明已经在我博客上贴出来 感兴趣的可以去看下Unreal4 <wbr>入门(安装)),虚幻4运行配置较高,大家赶紧去体验吧。


这次主要是简单介绍下Unreal4引擎使用前的配置 和 VisualStudio2013调试插件的配置


1. 在Unreal4安装目录下找到路径为 Unreal Engine\4.0\Engine\Extras 的文件夹。如下图:
 
Unreal4 <wbr>入门(配置)

可以很清晰的看到有 Android ,FX_tools , Maya_AnimationRiggingTools , MayaVelocityGridExporter , UnrealVS 与 VisualStuaioDebugging 这6个插件。

Android: 这个文件夹里主要是 安装AndroidSDK AndroidNDK 和 JDK 安装这些主要是为了在Win7平台下用Unreal4引擎直接打Android的apk包使用。

FX_tools: 这个文件夹里主要是3DMax2012的插件。

Maya_AnimationRiggingTools和MayaVelocityGridExporter: 这两个文件夹是Maya导出插件和编辑器工具

UnrealVS: 这个文件中有VS2012和VS2013两个版本的UnrealVS.vsix插件,只需要双击就可以安装了。 附图:
Unreal4 <wbr>入门(配置)
VisualStudioDebugging: 文件夹下有一个UE4.natvis文件(.natvis 文件是带 .natvis 扩展名的 .xml 文件),同学们需要把这个文件拷贝到 安装VisualStudio2013的按照目录下,路径为Microsoft Visual Studio 12.0\Common7\Packages\Debugger\Visualizers的文件夹中。 这样同学们就可以再VisualStudio2013中的调试栏的监控里看到 Unreal4引擎自定义的特殊类型的值啦Unreal4 <wbr>入门(配置)      附图:

Unreal4 <wbr>入门(配置)


2. 为什么建议各位同学使用Visual Studio 2013呢,不仅仅是因为Unreal4引擎对VS2013支持的最好。在Unreal4中还有比较特殊的用途就是,当你想为你的项目添加C++代码的时候你需要点击File菜单中的Add Code to Project按钮。 下面附张图:


Unreal4 <wbr>入门(配置)


下面这张图 警告同学们啦,必须需要使用Visual Studio 2013才能创建新的Class。 Unreal4 <wbr>入门(配置)

Unreal4 <wbr>入门(配置)

大概就介绍到这里啦。

  对于大型游戏MMORPG游戏或是3D街景(虚拟现实)还有大型无缝地图都需要地图啊,关卡动态加载的机制来达到让用户感觉自己一直是在漫游,而不会出现Loading(读条),卡界面等情况。当然除非是垮区域无法依靠关卡和关卡中之间的关系做处理。


     UnrealEngine4 作为一个多年处于世界前矛的商业引擎,自然而然也为大家考虑到这个这种硬性需求。UnrealEngine4 中的动态加载大概分为3种。

     首先需要明确下几点概念。因为再同学们信息会等的前提下才会更有利于理解和相互交流。好了,不瞎扯了进入正题。

     1.地图(Map):地图这个概念在UnrealEngine4中基本上所示虚拟出来。当然我们编译完一个场景后会保存到自己的工程目录下 如:XXXX\Content\Maps\  保存的文件名叫做.umap。一个工程下可以有很多很多.umap文件,但是我们需要注意到,我们在单独保存场景时编辑器都是基于Level操作的。代码中只有一个函数是关于地图[UEngine::LoadMap]。  如下图:

Unreal4 <wbr>入门(关卡动态加载)


    2.关卡(Level):关卡这个概念应该是在UnrealEngine4最常用使用的,在UE4编辑器中还有一个单独Levels编辑器。  如下图:

Unreal4 <wbr>入门(关卡动态加载)


    3.世界(World):World这个概念之前在UnrealEngine3中一直跟地图的概念差不多,World下面会有很多的Levels还有八叉树场景管理器,以及一些寻路啊,对Level和Actor的管理函数。当然现在也差不多,不过没有看见八叉树,多了一种LevelActor的类,SpawnActor中创建对象为"ConstructObject"之前创建对象另一个函数需要Outer和Owner的"DuplicationObject"。


言回正传:UnrealEngine4引擎提了我们有三种动态加载的方法,下面一一介绍。

一. 通过使用LevelStreamingVolume的方法:

    通过Modes窗口下的Volumes找到LevelStreamingVolume,拖动到编辑器中让它覆盖住同学们两个Level,调节LevelStreamingVolume的StreamingUsage属性(比如有加载后锁定,加载,加载后显示等)。
    当我们的Pawn进入到这个LevelStreamingVolume后关卡就会对应的加载啦。  如图:

Unreal4 <wbr>入门(关卡动态加载)

 加载类型设置属性图例

Unreal4 <wbr>入门(关卡动态加载)

二. 通过使用BluePrint的方法:

    通过打开关卡的Blueprints使用蓝图完成动态加载。那么在Blueprints中完成动态加载我们需要用到几个节点分别为 LoadStreamLevel和UnloadStreamLevel。 如图:

LoadStreamLevel节点
Unreal4 <wbr>入门(关卡动态加载)
UnloadStreamLevel节点
Unreal4 <wbr>入门(关卡动态加载)
    
    特别要注意的是LoadStreamLevel节点需要在MakeVisibleAfterLoad打勾,不然不会显示的呦。第二个暴露变量ShouldBlockonLoad打上勾会,不会被UnloadStreamLevel节点卸载(同学们自行按照需求选择呦)。还有一定要在Leves编辑器中把修改动态加载方法中的[总是加载]改成[蓝图]喔,不然通过Blueprints无法控制动态加载的。


三. 通过写代码的方式加载

    在需要切换动态加载关卡的时候,调用[UGameplayStatics::LoadStreamLevel]函数来加载想要使用的关卡。
    大概流程是创建一个FStreamLevelAction,这个Action回去读暴露参数的包遍历所有Level关系找到指定关卡,然后ActivateLevel这个关卡激活的时候会有加载或者卸载关卡。

PS:
    这几天一直在回忆之前使用UnrealEngine4学过的知识,也同时在看UnrealEngine4的新代码,如果出现概念混淆的情况或者叙述错误的情况,请各位同学指出并与我交流Unreal4 <wbr>入门(关卡动态加载)。  有机会请你们吃饭,喝咖啡。

C++和蓝图

概述

蓝图可以继承C++类,从而使得程序员可以在代码中创建新的游戏性类,而关卡设计人员可以使用蓝图来继承该类并对其进行修改。 有很多种修饰符可以改变C++类和蓝图系统间交互方式,其中某些修饰符会在本示例中突出介绍。

类设置

在类设置的第一部分中,使用C++类向导创建一个名称为LightSwitchBoth 的类。

LightSwitchBoth类中的大部分代码设置都和仅使用C++LightSwitch示例类似。尽管您可以让一个蓝图继承LightSwitchCodeOnly类,
但蓝图图表并不能访问该类中创建的组件、属性及函数。该示例将使用 UPROPERTY() 和 UFUNCTION() 修饰符,这两个修饰符使得LightSwitchBoth作为继承它的蓝图的模板。

您会发现首先参考下 仅使用C++LightSwitch示例是有用的,这样您可以看下如何设置头文件及源文件 来创建LightSwitchComponentSphereComponentDesiredBrightness属性及OnOverlap函数。

这个头文件是从 仅使用C++LightSwitch示例 改编而来,添加了以下功能:

PointLightComponentSphereComponentBlueprintReadOnly(仅蓝图可读的),并且将显示在 我的蓝图 选卡中的 Switch Components(切换组件) 类目中。

OnOverlap现在是一个BlueprintNativeEvent,将会显示在 我的蓝图 选卡中的 Switch Functions(切换函数) 类目中。

DesiredBrightnessBlueprintReadWrite(蓝图可读写的),将显示在 我的蓝图 选卡中的 Switch Properties(切换属性) 类目中。

DesiredBrightness现在是EditAnywhere(随处可编辑的),而不是VisibleAnywhere(随处可见的)

UCLASS() 宏有个 Blueprintable 修饰符。在这个示例中,该修饰符不是必须的,因为LightSwitchBoth直接继承Actor,而ActorBlueprintable(可蓝图化的),所以LightSwitchBoth会继承该修饰符。

加上 UPROPERTY() 和 UFUNCTION() 宏中的额外修饰符,LightSwitchBoth类的头文件如下所示:

LightSwitchBoth.h

// Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.

 

#pragma once

 

#include "LightSwitchBoth.generated.h"

 

UCLASS()

class ALightSwitchBoth public AActor

{

    GENERATED_UCLASS_BODY()

 

   

    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Switch Components")

    TSubobjectPtr PointLight1;

 

   

    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Switch Components")

    TSubobjectPtr Sphere1;

 

   

    UFUNCTION(BlueprintNativeEvent, Category="Switch Functions")

    void OnOverlap(class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

 

   

    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Switch Properties")

    float DesiredBrightness;

};

 

在LightSwitchBoth的源文件中,构造器仍然是一样的。但是,需要对 OnOverlap 函数做一点修改。这个函数现在是一个BlueprintNativeEvent。这意味着 在继承这个类的蓝图中,可以放置一个覆盖 OnOverlap 的事件,当正常调用该函数时会执行此事件。如果该事件不存在,那么则是执行那个函数的 C++实现。要想使这个设置正常工作,该C++函数需要重命名为 OnOverlap_Implementation 。稍后在本示例中将介绍这个蓝图设置。对 OnOverlap 函数 进行了修改后,LightSwitchBoth 的源文件如下所示:

LightSwitchBoth.cpp

// Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.

 

#include "BasicClasses.h"

#include "LightSwitchBoth.h"

 

ALightSwitchBoth::ALightSwitchBoth(const class FPostConstructInitializeProperties& PCIP)

    Super(PCIP)

{

 

    DesiredBrightness 15.0f;

 

    PointLight1 PCIP.CreateDefaultSubobject(this, "PointLight1");

    PointLight1->Brightness DesiredBrightness;

    PointLight1->bVisible true;

    RootComponent PointLight1;

    Components.Add(PointLight1);

 

    Sphere1 PCIP.CreateDefaultSubobject(this, TEXT("Sphere1"));

    Sphere1->InitSphereRadius(250.0f);

    Sphere1->OnComponentBeginOverlap.AddDynamic(this, &ALightSwitchBoth::OnOverlap);        // set up notification for when this component overlaps something

    Sphere1->OnComponentEndOverlap.AddDynamic(this, &ALightSwitchBoth::OnOverlap);      // set up notification for when this component overlaps something

    Sphere1->AttachParent RootComponent;

    Components.Add(Sphere1);

}

 

void ALightSwitchBoth::OnOverlap_Implementation(AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)

{

    if OtherActor && (OtherActor != this) && OtherComp )

    {

        PointLight1->ToggleVisibility();

    }

}

当创建类时,新的 UCLASS() UFUNCTION() /或 UPROPERTY() 宏意味着该代码必须在Visual Studio Xcode中进行编译,然后使用虚幻编辑器重新加载它们。 关闭虚幻编辑器,在Visual Studio Xcode中编译该项目,然后打开编辑器并重新加载该项目,以确保正确地重新加载该游戏模块。同时,需要注意的一点是, 要确保 Build Configuration(版本配置) 和您打开该项目使用的虚幻编辑器可执行文件的版本一致。 请在 编译游戏项目文档中阅读关于编译配置及编译项目的更多信息。

当重新打开虚幻编辑器并重新打开您的项目后,便可以创建一个新的类蓝图了。 在本示例中,选择LightSwitchBoth作为该蓝图的父类,蓝图名称为LightSwitchBoth_BP 


Unreal4 <wbr>入门 <wbr>使用C++和Blueprints

在 C++代码中添加的PointLightComponentSphereComponent 也会显示在 Blueprint Editor(蓝图编辑器) 的 组件模式中的 Components(组件) 选卡内。 它们的图标是深蓝色,表示它们是从父类LightSwitchBoth类继承而来的原生组件。而刚刚添加到 LightSwitchBoth_BP 蓝图中的新组件的图标 是浅蓝色的。关于使用 Components(组件) 选卡添加及排列组件的更多信息,请参照 组件选卡文档。

Blueprint Editor(蓝图编辑器) 的 图表模式是蓝图编辑的核心。在 Graph Mode(图表) 模式中,您可以在我的蓝图选卡中添加新变量、 函数。您也可以访问该类蓝图中包含的 所有 图表。在这些图表中,各种节点连接到一起,来创建由类属性、游戏事件、甚至Actor的周边环境 驱动的设计及游戏功能。

在 Graph Mode(图标模式) 中, My Blueprint(我的蓝图) 选卡显示了在C++中添加到LightSwitchBoth类中的 PointLightComponent SphereComponent 。这是因为 BlueprintReadOnly 修饰符存在的缘故。 通过在 我的蓝图 选卡中点击并拖拽这些组件的名称到图表中,可以将这些组件的节点添加到图表中。然后,您可以把这些节点连接到改变像可见性 或光源颜色这样属性的节点上。DesiredBrightness 属性也会出现在 我的蓝图 选卡中。因为它是一个属性,而不是一个组件,所以可以使用 BlueprintReadWrite 修饰符。这意味着在蓝图图表中可以创建节点来获取及设置 DesiredBrightness 的值。请参照 我的蓝图文档来获得一般的应用信息。

默认情况下,可能不会显示父类LightSwitchBoth的组件和属性。因为当选中 我的蓝图 选卡底部的 Show user-created variables only(仅显示用户创建的变量) 复选框时, 会隐藏从父类继承的属性。

                     显示所有变量

Unreal4 <wbr>入门 <wbr>使用C++和Blueprints

             仅显示用户创建的变量

Unreal4 <wbr>入门 <wbr>使用C++和Blueprints

有两个图表用于设置 LightSwitchBoth_BP 类的行为。第一个是构造脚本图表,它包含了一个专用的 Construction Script(构建脚本)
事件。如果没有该 Construction Script 设置,那么新的 LightSwitchBoth_BP Actor 将仅使用LightSwitchBoth的构造函数。然而,当Actor在关卡中移动时,及当 Desired Brightness 发生改变时,都会执行 Construction Script 。使用 Construction Script 意味着,可以轻松地改变暴露给蓝图的Actor属性, 并且可以快速地看到这些修改的效果。

在 LightSwitchBoth_BP 类中, Construction Script 事件连接到了 Set Brightness 节点上,以便当在关卡中添加或移动Actor时或者 Desired Brightness 发生改变时,将 Point Light 1 (PointLightComponent) 的亮度设置为 Desired Brightness 的值。


Unreal4 <wbr>入门 <wbr>使用C++和Blueprints


LightSwitch_BPOnly 类中设置的另一个图表是 事件图表 EventGraph的执行是由事件触发的。在这个示例中, 任何时候当调用C++函数 OnOverlap 时,OnOverlap 就会执行。在LightSwitchBoth的源文件中,设置了代理,以便当一个Actor进入或离开SphereComponent时会执行 OnOverlap 

Sphere1->OnComponentBeginOverlap.AddDynamic(this, &ALightSwitchBoth::OnOverlap); // set up notification for when this component overlaps something Sphere1->OnComponentEndOverlap.AddDynamic(this, &ALightSwitchBoth::OnOverlap); // set up notification for when this component overlaps something

OnOverlap 事件节点连接到了 Set Light Color 节点上。任何时候当执行该事件时,它都将会把PointLightComponent的光源颜色设置为一个随机颜色。这覆盖了 源码文件中用于切换的PointLightComponent可见性的 OnOverlap_Implementation 函数。

关于事件及处理图表的更多信息,请参照事件、 事件图表事件模式 文档。


Unreal4 <wbr>入门 <wbr>使用C++和Blueprints

在变量的设置中, DesiredBrightness 变量设置为 EditAnywhere (随处可编辑) ,所以在 蓝图编辑器 默认模式中它是可见的,并且可以进行编辑。 这意味着对于类的每个实例,这个变量是可以变化的,所以每个Actor可以有其自己的 DesiredBrightness 。因为 DesiredBrightness 也是 BlueprintReadWrite(蓝图可读写) 的,且 Construction Script 中使用了它,所以更新它还会导致再次执行 Construction Script 

其他Class Blueprints(类蓝图)可以继承由蓝图创建的类,通过以下两种方式实现:使用 Class Viewer(类别查看器) 中的类附近的下拉列表按钮来创建一个新蓝图, 或者通过右击该蓝图并选择 Create New Blueprint Based on This(基于此蓝图创建一个新蓝图) 

类蓝图 LightSwitchBoth_BP 位于 内容浏览器中,您可以从那里将其拖拽到关卡内。它也存在于 类别查看器中。 关于使用 内容浏览器 或 类别查看器 在关卡放置Actor的更多信息,请参照放置Actors 文档。

 

 


虚幻引擎4设置Visual Studio

设置Visual Studio和虚幻引擎4协同工作有利于提高开发人员使用UE4 的效率和整体用户体验。

推荐设置

以下是为结合使用Visual Studio和虚幻引擎4的开发人员推荐的设置。

  • 关闭 Show Inactive Blocks(显示不活动的代码块) 。如果您不关闭此项,在文本编辑器中,很多代码块会呈现出灰掉 状态。(Options(选项) > Text Editor(文本编辑器) > C/C++ > Formatting(格式)) 

  • 打开IntelliSense(智能编码)和"squiggles(波浪线提示)"功能,让它们正常运行。(请参照Intellisense(智能编码), Live Errors(实时错误)和Squiggles(波浪线提示)部分)

  • 在Visual Assist X (VAX)中关闭 Format After Paste(粘帖后格式化) 功能。这个功能有时候会导致格式变得混乱。(VAX Options(VAX选项) > Advanced(高级) > Corrections(校正))

  • 在解决方案浏览器中停用 External(外部) 文件夹, 它们会扰乱视图。( 在 Options(选项) > Text Editor(文本编辑器) > C/C++ > Advanced(高级) Disable External Dependencies Folder(禁用外部依赖文件夹) )

  • 如果不需要 Edit & Continue(编辑&继续) 功能,请关闭它们。(Options(选项) > Debugging(调试) > Edit and Continue(编辑并继续))

  • 关闭 Error List(错误列表) 窗口。如果启用该功能,当您的代码中出现合法错误时 Error List(错误列表) 窗口会自动弹出 。但是,当和虚幻引擎结合应用时, Error List(错误列表) 会显示不正确的错误信息。建议您最好 禁用该窗口,并使用 Output(输出) 窗口来查看您的代码错误。这个窗口将仅显示 真正的错误。要想禁用Error List(错误列表)窗口:

    • 如果 Error List(错误列表) 窗口处于打开状态,请关闭它。

    • 从 Tools(工具) 菜单中, 打开 Options(选项) 对话框。

    • 选择 Projects and Solutions(项目和解决方案) 并取消选中 Always show error list if build finishes with error(如果编译中出现错误总是显示错误列表) 选项。

Intellisense(智能编码)、Live Errors(实时错误)和Squiggles(波浪线提示)

虚幻引擎4项目现在可以正常支持 IntelliSense(智能编码)功能,包括实时Error List(错误列表) 和 "squiggles(波浪线提示)"! (请参照以下介绍获得如何启用它的信息。)

VC10的IntelliSense功能可以在您编写代码的过程中重新编译C++。这比仅检查 VAX的语法强大很多: VC10使用完整的C++编译器,可以验证每一行代码。这个功能非常强大并且将会 加快您的工作流程!

VC++ Intellisense Squiggles

当其和波浪线提示功能结合使用时,如果您正在查看的文件有任何IntelliSense 错误,都可以在Error List(错误列表)中看到。 您可以通过Error List(错误列表)的右击菜单来打开或关闭该功能。

VS 2010 Error List

由于Squiggles(波浪线提示)功能不能和虚幻引擎4项目协同工作,您可能已经禁用了它们。请确保点击 C/C++ Advanced(高级)选卡,并使用以下设置。

VC++ Advanced Options

当您打开一个C++文件时,您可以通过查找这个图标来判断IntelliSense编译器是否正在“工作”:

Intellisense Progress Indicator


实现细节

  • 当编写代码时显示波浪线提示有时候要花几秒钟的时间。

    • 这是因为我们有很多包含文件,且IntelliSense目前不使用预编译头文件。

  • 有时候您会看到“误报的”IntelliSense 错误。以下是几种可能的原因。

    • IntelliSense编译器(EDG)比MSVC编译器更严格。

    • 某些针对IntelliSense的#defines设置和正常编译时的设置不同。

    • IntelliSense编译的C++总是被当做32位对待。

  • 如果绝对需要,您可以把代码封装到 #ifdef __INTELLISENSE__ 中,以消除波浪线提示。

  • IntelliSense的错误的表达方式和VC++ 编译器的错误的表达方式略有不同。他们只是表达不同而已。

  • 头文件中的Squiggles(波浪线提示)功能通过编译包含它的已知 .cpp 对应的头文件来进行工作。

    • 有时候IntelliSense把这个功能搞乱了,导致您会在头文件中看到波浪线提示。

  • 如果需要,您可以增大 Max Cached Translation Units(最大缓存变换单元) 设置。

    • 它会使用更多的内存,但可能会提高一点反应速度。

  • 有少量C++文件还不能和IntelliSense相兼容。

  • Unreal Build Tool有一个新的 -IntelliSense 选项。

    • 这将为我们的所有项目文件产生IntelliSense属性表。

    • 当添加了新的模块或者项目包含发生改变时仅需要重新运行它即可。

UnrealVS 插件

Visual Studio的UnrealVS插件使您可以在使用虚幻引擎开发时轻松地访问常用操作。

unrealvs_toolbar_cmd.png

功能包括:

  • 设置启动项目

  • 编译启动项目的可绑定命令

  • 设置命令行参数

UnrealVS插件不能和Visual Studio 2012精简版协同工作。它仅能和Visual Studio 2012 专业版相兼容。

请参照UnrealVS插件页面 获得设置及使用该插件的信息。


调试

Visual Studio支持通过‘可视化查看器’来扩展调试器,从而轻松地查看常见的虚幻数据类型, 比如对象FNames 和动态数组。根据您所使用的Visual Studio 2010或Visual Studio 2012的不同, 这个功能的设置也有所区别。

针对Visual Studio 2012的可视化查看器设置

您会发现您的安装文件中包含了具备该可视化查看器逻辑的文件:

[ROCKETINSTALL]/Engine/Extras/VisualStudioDebugging/UE4.natvis

复制该文件到以下位置:

[VSINSTALLDIR]/Common7/Packages/Debugger/Visualizers/UE4.natvis [USERPROFILE]/My Documents/Visual Studio 2012/Visualizers/UE4.natvis

继续研究Blueprint,这次主要看看C++和Blueprint的结合方法。官方文档依然没有太大用处,但在wiki上还是有很多值得学习的文章的。当中有个叫Rama的家伙贡献了相当多的教程,他还写了一个很不错的插件,而且将源代码和实现的思路都写在了一个wiki页面里,对社区的帮助很大,MVP应该是没得跑了,要是多一些这样的人UE4就能更快地成熟并推广了。

不过在动手写代码之前,我首先把那个忍无可忍的VS2013自带的Intellisense给关掉了,我是完全按照官方文档的指引配置了所有的参数,但实际用起来却奇慢无比,再小的工程敲几行代码后要等二十几秒自动完成才能蹦出来,右下角那个处理提示符就几乎没消失过。而且代码帮助还非常不稳定,时有时无,另外还经常给出一些错误的提示。忍不了了,还是装了Visual Assist,瞬间一切都那么顺手又顺眼了。

工具搞定后,先来看看如何在C++中创建可以在Blueprint中使用的全局函数:

  • 创建一个继承自UBlueprintFunctionLibrary的C++类即可。不知道为什么在Editor中不能直接创建基于UBlueprintFunctionLibrary的C++类,但我们可以在VS中自己修改一下基类
  • 继承自UBlueprintFunctionLibrary类中,凡是具备BlueprintCallable属性的UFUNTION即可在Blueprint中被调用
  • 如果UFUNCTION还带有BlueprintPure属性,那么意味着这个函数不会修改任何游戏状态,因此无需exec链的触发(在Blueprint中体现为没有白线输入),可以在任何时刻被调用获取其结果
  • 作为随时可被调用的全局函数,都需要被声明成static函数

下面是具体代码:

MyBPLibrary.h:

复制代码
 1 // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
 2 
 3 #pragma once
 4 
 5 #include "MyBPLibrary.generated.h"
 6 
 7 
10 UCLASS()
11 class UMyBPLibrary : public UBlueprintFunctionLibrary
12 {
13     GENERATED_UCLASS_BODY()
14         
15     UFUNCTION(BlueprintCallable, BlueprintPure, Category = "Test")
16         static FString GetHappyMessage();
17 
18     UFUNCTION(BlueprintCallable, Category = "Test")
19         static bool SaveToFile(FString Dir, FString Name, FString Text, bool Overwrite = false);
20 
21     UFUNCTION(BlueprintCallable, Category = "Test")
22         static bool MakeDir(FString Dir);
23 };
复制代码

MyBPLibrary.cpp:

复制代码
 1 // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
 2 
 3 #include "HelloWorld.h"
 4 #include "MyBPLibrary.h"
 5 
 6 
 7 UMyBPLibrary::UMyBPLibrary(const class FPostConstructInitializeProperties& PCIP)
 8     : Super(PCIP)
 9 {
10 
11 }
12 
13 FString UMyBPLibrary::GetHappyMessage() {
14     return FString("Hello, I'm Happy!");
15 }
16 
17 bool UMyBPLibrary::MakeDir(FString Dir) {
18     return FPlatformFileManager::Get().GetPlatformFile().CreateDirectory(*Dir);
19 }
20 
21 bool UMyBPLibrary::SaveToFile(
22     FString Dir,
23     FString Name,
24     FString Text,
25     bool Overwrite 
26 ) {
27     IPlatformFile& F = FPlatformFileManager::Get().GetPlatformFile();
28     if (!F.DirectoryExists(*Dir))
29     {
30         F.CreateDirectoryTree(*Dir);
31         if (!F.DirectoryExists(*Dir))
32         {
33             return false;
34         }
35     }
36 
37     Dir += "\\";
38     Dir += Name;
39 
40     if (!Overwrite)
41     {
42         if (F.FileExists(*Dir))
43         {
44             return false;
45         }
46     }
47 
48     return FFileHelper::SaveStringToFile(Text, *Dir);
49 }
复制代码

这个例子中实现了3个全局函数:GetHappyMessage,MakeDir以及SaveToFile,其中GetHappyMessage为无副作用的函数。它们在Blueprint中就可以这么用了:

在调试的过程中遇到的一些问题在这里说一下:

  • 在Rama的例子中,对文件的操作都是基于GFileManager,但在实际写代码时发现这个全局变量不存在,只能通过FPlatformFileManager来实现相关操作,可能是Rama写教程之后UE4的代码又发生过变化
  • 在Blueprint中,那些紫色的节点代表一个String类型的输入,但是这里需要注意:在输入框里不要将字符串包围在双引号之间了,也不要对特殊字符转义,系统会帮你处理。一开始不清楚在这里卡了好久
  • 如果你自己的类是继承自PlayerController,那么可以使用ClientMessage来输出一些调试信息;但如果不是(比如上面的这个例子),则可以使用UE_LOG宏,宏的用法和Rama教程里的用法也不太一样了,需要自己去研究一下

通过在C++中实现供Blueprint调用的全局函数,就实现了Blueprint和C++交互的一种常用途径。后面再写一些其他交互方式的实现方法。


C++触发Blueprints事件

如果想实现只供某一个类使用的Blueprint函数,方式是类似的,只是不要再继承UBlueprintFunctionLibrary类,同时函数也无需再声明成static即可。

虽然能够在Blueprint中调用一个C++实现的方法是很不错,但在实际中我们还会需要其他的交互方式,比如由C++代码去触发一系列的Blueprint动作,以及让Blueprint能够和C++类的某些属性变量直接进行交互。

我们先来看看如何将C++类中的某些属性变量暴露出去,让Blueprint(或Editor)能够看见、读或写这些变量,从而实现和C++的通信。

其实非常简单:只需要在C++类的头文件中这样声明一下就可以了:

1 
2     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PlayerMusicSkill")
3     int32 MusicSkillLevel;

只需要使用UPROPERTY宏,在加上一些枚举属性,就可以让一个变量以开发者希望的方式暴露给Blueprint,其中:

  • EditAnywhere表示该变量可以在Editor中任意进行修改,而VisibleAnywhere则表示Editor中只能看、但无法修改这个变量,还有几个其他的可选项供选择,可以自行研究代码
  • BlueprintReadWrite表示该变量可以在Blueprint中读或写,BlueprintReadOnly则表示在Blueprint中只能读
  • Category表示在Editor和Blueprint列表中这个变量归到那一分类,这主要是一个方便开发者寻找的功能,没有其他特别作用
  • 头部的注释不仅仅是代码中的注释,它也会作为这个参数的帮助提示显示在Editor的界面上

上面的代码在编译后,只需要在Editor中基于这个类创建一个Blueprint,然后就能够在它的Default属性界面看到下面的内容:

相当不错,而且简单。下面再来看看关键的:如何让C++去触发Blueprint,同时给Blueprint传递信息?

其实也非常简单,主要是使用UFUNTION+BlueprintImplementableEvent属性:

1 UFUNCTION(BlueprintImplementableEvent, meta = (FriendlyName = "Music skill is GOOD"))
2         virtual void MusicSkillGood(int32 CurrentSkill);

其中:

  • BlueprintImplementableEvent表示下面定义的函数会触发Blueprint里的一个事件,但事件触发后如何处理则由Blueprint自行实现,C++代码不负责,它只负责在适当的时候调用下面的函数并传递参数数据而已
  • meta相关内容和Category类似,主要是给用户提供一个更容易分辨的信息。在这里这个自定义事件在Blueprint中就会被显示为“Music skill is GOOD”,没有其他作用
  • MusicSkillGood就是用来在C++中触发Blueprint事件的函数,它一定要被定义为虚函数,而且返回值一定要为void,因为这个函数的实现不由C++来做,它只是提供一个触发的手段,且所有的数据都通过其参数传递给Blueprint

完整的类代码如下:

MyPlayerController.h:

复制代码
 1 // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
 2 
 3 #pragma once
 4 
 5 #include "GameFramework/PlayerController.h"
 6 #include "MyPlayerController.generated.h"
 7 
 8 
11 UCLASS()
12 class AMyPlayerController : public APlayerController
13 {
14     GENERATED_UCLASS_BODY()
15     
16     
17     UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "PlayerMusicSkill")
18     int32 MusicSkillLevel;
19 
20     UFUNCTION(BlueprintImplementableEvent, meta = (FriendlyName = "Music skill is GOOD"))
21         virtual void MusicSkillGood(int32 CurrentSkill);
22 
23     virtual void PlayerTick(float DeltaTime) OVERRIDE;
24 };
复制代码

MyPlayerController.cpp:

复制代码
 1 // Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
 2 
 3 #include "HelloWorld.h"
 4 #include "MyPlayerController.h"
 5 
 6 
 7 AMyPlayerController::AMyPlayerController(const class FPostConstructInitializeProperties& PCIP)
 8     : Super(PCIP)
 9 {
10 
11 }
12 
13 void AMyPlayerController::PlayerTick(float DeltaTime) {
14     Super::PlayerTick(DeltaTime);
15 
16     if (MusicSkillLevel > 50)
17     {
18         MusicSkillGood(MusicSkillLevel);
19     }
20 }
复制代码

上面代码的主要逻辑就是在每个Tick检查当前类实例的MusicSkillLevel变量值是否大于50,如果是,则对Blueprint触发MusicSkillGood事件,并将MusicSkillLevel的值传递过去。最终在Blueprint中可以这样用:

这个Blueprint的逻辑就是:

  • 每当用户按M键,就将MusicSkillLevel变量的值加1
  • 而如前所述,C++代码会在每个Tick检查MusicSkillLevel的值是否大于50,如果大于50了,那么就会在每个Tick都触发一次MusicSkillGood事件(由于meta的设置,这个事件被显示成“Music Skill is GOOD”)
  • 当用户按了足够多的M键导致MusicSkillLevel变量的值超过50时,在游戏中就能看到MusicSkillLevel的当前值在刷屏了

到此为止,Blueprint已经和C++代码实现了完全的交互:Blueprint能够主动调用C++中的函数,C++也能主动触发Blueprint的事件,而且双方还能通过暴露的变量进行交互。这样一来,整个游戏的底层平台模块完全可以用C++实现,然后给上层的Blueprint提供调用接口,由Blueprint来利用、组织这些模块来实现上层的完整游戏逻辑。这种结合方式既保留了C++的性能优势,又充分利用了Blueprint的易用性和灵活性来让游戏开发保持快速地迭代。这应该就是UE4所推崇的最佳开发模式。

   接触UnrealEngine4大概有快两周了,从安装配置到编辑器的熟悉,再到官方实例的学习以及Blueprint的应用。从UE3的UnrealScript和各种classes到UE4现在的发开方式,昨天大概拟定了一个UE4引擎探究的计划,下周会围绕计划展开研究。

    这几天再看UnrealEngine4的代码,在写代码的过程中有些注意事项跟大家分享一下,也算给自己做个记录Unreal4 <wbr>C++使用注意事项

一. 最好不要自己在UnrealEngine4的工程中添加代码文件,尤其是.h文件。因为UE4的UnrealHeaderTool会根据UnrealEngine4的反射机制自动生成一个.generated.h文件(应该是UnrealBuildTool需要注册并做反射用)。添加代码最好是通过编辑器的创建类向导创建。  如图例:

Unreal4 <wbr>C++使用注意事项
    如果想用更多的类作为父类的话,可以点击“右上角”显示所有类。这样的话比如我们想做一个管理器类不需要其他逻辑业务功能我们就可以在 显示所有类 中选择一个UObject作为父类喽,配图如下:

Unreal4 <wbr>C++使用注意事项
点击"显示所有类"后,如图:

Unreal4 <wbr>C++使用注意事项

二. UnrealEngine4的C++代码有套自己的浅规则,如同Unity3D的限制版C#一样。请各位同学们不要忙着抱怨Unreal4 <wbr>C++使用注意事项,经过了13多年承载和UnrealScript的经验想必Epic不会自找苦吃把自己开发饭碗搞的很糟糕。目前笔者看到的优点是拥有GC机制,支持Blueprint和编辑器的反射机制,UnrealBuildTool的运行时编译,还有一些自动化生成功能。闲话不多说,来点干货先。

  1. 声明类时需要添加UCLASS()宏,可以带参数用来标示在编辑器中的名称,暴露类别,显示类别,类别构造,API类型,Blueprint类型,配置文件=名称。
例如:

Unreal4 <wbr>C++使用注意事项
  2. 声明变量时需要添加UPROPERTY()宏,可以带参数用来标示 在哪里时可见,高级显示类型,属于哪个类别,标签[类似注释]。
例如:
Unreal4 <wbr>C++使用注意事项
 3. 在XXXX.h文件中引用其他头文件,请各位同学一定要在把#include "xxx.h" 放到这个XXXX.h文件#include "XXXX.generated.h" 前,不然会报错呦。
例如:
Unreal4 <wbr>C++使用注意事项

4. 下周UnrealEngine4就要更新4.1版本了,最近UE4还属于公测版有不少不稳定的地方,当然官方的更新的速度也很快。在目前这个情况下笔者比较建议采用Unity3D脚本开发的程序结构。做一个自己的逻辑模块聚合到自己的GameMode或者WordSettings下。再由自己的逻辑模块去驱动游戏逻辑调用或者驱动UnrealEngine4的其他模块,开发者把大部分精力放在逻辑模块的架构上和引擎功能模块的调度上,不要上来就想去从GamePlay的入口去改引擎底层的逻辑架构。

原因如下:
1). UnrealEngine4引擎目前还不是很健壮,可能会在开发流程和开发模式上做出变动。
2). UnrealEngine4试图把很多精力放在把大家想Blueprints上去引导,大力推动开发者用Blueprints完成游戏开发。游戏逻辑和Blueprints关联很紧密,如果处理不好久有点得不偿失了会浪费大量时间和精力。


预祝大家开发顺利,欢迎随时沟通 互相学习和进步Unreal4 <wbr>C++使用注意事项


2016-11-21 23:30:27 u013131744 阅读数 4990

首先要说的是,游戏开发是一项高度复杂的代码开发工作,编程语言只是最基本的知识,它涉及的内容还有计算机图形学、3D数学、物理学等复杂的学科。但是若需要学完这么多知识才能开发游戏,恐怕许多人都已经断气了,更谈不上开发游戏了。所以前人就把各种复杂的代码封装起来,使得一般的游戏开发者可以更加接近游戏的逻辑和功能性方面的代码,而无需接触最底层的知识。

194023hhhqhbpcqpmpltad

所以说游戏引擎,可以是引擎开发者已经写好的一堆代码框架,使得我们可以去调用这些底层代码,也可以是像虚幻4还附带可视化关卡编辑器的工具(Unity3D也是可视化的游戏引擎,后面会谈当今主流游戏引擎的对比)。

为什么选用虚幻4引擎?

首先,现在流行而且出名的商业引擎主要有cocos2dx,Unity3D,UE4,CryEngine等。但是这里选择UE4,也有笔者认为的独特优势。

1) UE4是开源的。开源就是代码是完全开放的,为什么开源如此重要?一方面是因为只有我们看到源代码的实现细节,当出错了我们才能快速准确地判断出错的成因,节省被错误折腾的时间。(你想想像Unity3D这种闭源引擎,要是出错了,你是完全看不到为什么会发生错误的。除了不断盲目Debug,查文档和谷歌之外自己对于错误束手无策。)另一方面,开源可以使得我们深入学习引擎的原理,只知其然不知其所以然必然不能走得太远,而且会走得更痛苦。

2) UE4的画质是世界上数一数二的。游戏的画质往往由游戏引擎来决定的,一个好的游戏引擎它可以模拟出极度逼真或者极具美感的画面。读者可以自己去看看Unity3D制作的游戏和UE4制作的游戏,其精美程度是相差甚远的。(这里并不是完全指责Unity3D,毕竟它们面对的是不同的层次。)作为一名追求极致的游戏程序员,当然要想看看最好的效果是怎么实现的。

3) UE4免费!无需多言,还有比免费更好的事吗?

下图为UE4游戏引擎制作出来的极度逼真游戏画面,你分得清这是不是现实吗?

虚幻4游戏引擎有何强大之处?

第一代虚幻游戏引擎(英文名是Unreal Engine,简写UE)在1998年由Epic Games公司发行。当时Epic Games公司为了适应游戏编程的特殊性需要而专门为虚幻系列游戏引擎创建了一种名为UnrealScript的编程语言,该语言让这个游戏引擎变得非常容易方便,因而这个游戏引擎开始名声大振。

接着,2002年,Epic发布了下一代游戏引擎UE2。这时候,在虚幻引擎提供的关卡编辑工具UnrealEd中,能够对物体的属性进行实时修改。它也支持了当时的次世代游戏机,像PlayStation2,XBox等。

到了2006年,Epic发布了下一代游戏引擎UE3,这可能是最受欢迎和广泛使用的游戏引擎。这时候的UE3又发布了一个极其重要的特性,那就是Kismet可视化脚本工具,Kismet工作的方式就是以用各种各样的节点来连接成一个逻辑流程图。其最牛逼的地方在于,使用Kismet你甚至不需要掌握任何编程知识。你可以借助Kismet使得不需要写一行代码来开发一个完整的游戏。 

到了2014年5月19日,Epic发布了Unreal4,目前最新也是Unreal4。这次版本换代也是有了巨大的改变,它已经完全移除了UnrealScript语言,并且用C++语言来代替它。在之前的版本,如果你想修改这个引擎来开发你自己的游戏,你必须用UnrealScript,也就意味着你要学习一门新的语言。不过现在,如果你要修改这个引擎,你可以用C++来完成。这对于绝大部分习惯于C++的游戏引擎工程师来说,使用自己热爱的C++语言来工作,绝对是一件天大的喜事啊。 

不但如此,游戏引擎的源代码已经可以从Github开源社区下载。这意味着开发者对游戏引擎有着绝对的控制权,实质上你可以修改任何任何东西,包括物理引擎、渲染和图形用户界面。 

它也提供了一些叫热更新的功能。什么叫热更新呢?通常,如果你想对游戏的代码进行一些修改,你必须要停止游戏才能进行修改,然后再次运行看看修改后游戏的效果。然而,使用热更新功能,你可以修改游戏而不需要停止或暂停游戏。任何在游戏代码的改变会即时更新,并且你可以看见它会在游戏中实时反映出来。 

UE4是跨平台的,你可以用来制作Xbox One、PlayStation4(包括索尼的Project Morpheus虚拟现实设备),Windows PC,Linux,Mac OSX,HTML5,iOS和安卓,就连虚拟现实设备Oculus Rift也支持。 

另一个重大的改变是,在2015年初,虚幻4已经可以完全免费下载和使用了,之前的版本是需要支付一定费用的。现在,你可以用来开发游戏,并且发行,而且不需要为UE4游戏引擎支付一分钱。只有在你赚到了3000美元收益之后,你才需要支付5%的技术使用费。 

另一个UE4提供的特性是商城,你可以在商城中购买和上传游戏资源。这些游戏资源可以包括动画,3D建模,材质,声音效果,预制游戏等等。这也是一个令没有游戏资源或者没有人力来开发资源的开发者振奋的消息。它们可以商场购买并直接应用于自己的游戏中。开发者也可以上传自己的工作成果到商城来赚钱。 

这个虚幻4小白系列教程,是面向于没有使用过UE4的新手,但需要一点点C++的知识(但也无需太多,一般读过任何一本C++教材都能看懂本教程)。我们从非常基础的下载安装引擎开始,到更高级的上传作品到谷歌PlayStore,都会涉及。我们会使用UE4来一步一步地制作我们的游戏,Let’s Start From it,你的游戏开发之路!

下图为UE4游戏引擎制作出来的官方示例宣传视频画面:



2016-11-22 13:34:52 u013131744 阅读数 2327

200736dbc2jxd3bxhjsrcj

一. 创建空白关卡1) 点击文件 -> 新建关卡(或者按快捷键Ctrl+N)。


2) 你可以选择Default(默认)或空关卡。不过选择空关卡比较好,理由迟些会解释。


3) 新的空关卡会一片漆黑。现在让我们从内容浏览器中添加一些物体到场景中去。将StarterContent/Shapes中的Shape_Plane拖动到场景中。点击场景中的平面,然后按F键聚焦。然后按下R键,拖动立方体使得平面放大。点击场景中的平面,然后将StarterContent/Materials中选择M_Ground_Moss拖放到平面中去来改变其材质。效果如下图所示:


4) 在StarterContent/Props中选择SM_Rock拖放到场景中去。通过按R键,然后拖放小方块来调节岩石的大小。


5) 在StarterContent/Particles中选择P_Fire拖放到场景中,效果如下图所示:


6) 接下来我们放置灯光。在左侧的模式面板中选择点光源,拖放到场景中去。

二. 添加碰撞体

点击播放,你会注意到我们的摄像头可以通过WASD或箭头键和鼠标来移动,但是可以穿透岩石体,这明显不合常量,所以现在我们先来把岩石添加上碰撞体的属性。碰撞体是用于模拟物理的物体碰撞属性,我们可以通过网格-网格来检测碰撞,不过需要花费很高的开销。所以我们使用近似的包围盒来估算碰撞体。

1) 点击场景中的岩石。

2) 在世界大纲视图中右键该岩石,选择编辑,如下图所示:


3) 然后会打开一个网格编辑器。确保下图中的碰撞网格显示按钮已经开启。


4) 选择上方的碰撞菜单,然后选择“添加胶囊简化碰撞”来模拟出近似的岩石形状的碰撞体:


5) 你可以通过W(平移)、E(旋转)、R(缩放)来调整碰撞体的网格大小:


6) 点击左上角的保存。然后点击播放,你会发现摄像机已经穿不过该岩石了,因为此时岩石具有一个碰撞包围体了。

这时候我们就完成了对岩石添加碰撞体的操作了。


转自:http://www.52vr.com/article-560-1.html