/images/avatar.png

Papalqi

ActorPalete

UE4 .26或悄悄添加了曾经是“演员面板(Actor Palete)”插件的东西。顾名思义,这个actor调色板是一个插件,它可以让您加载其他level的角色从它们拖动到当前level。 一旦激活了Actor Palette插件,请从顶部菜单的“窗口”->“ Actor Palette”中打开一个Actor Palette。 当打开一个新窗口时,它将如下所示。 您可以在Actor Palette中打开一个关卡,方法是从Actor Palette窗口中选择“打开关卡”,然后选择您实际要打开的关卡。

Niagara 源码架构解析

从git上的信息其实可以看到,Niagara其实在引擎中存在的时间非常久,在4.0版本就已经存在。但是直到2018年的4.17中公开出来。4.17~4.24 为实验版本,4.25 之后正式版本。但是从目前官方的对于Niagara fix的代码提交上看,还是有相当多的编辑器问题修复。 17年才将Niagara从Engine内部移植到插件中。 随着长久的历史变迁,Niagara已经进行了多次的文件位置上的转移,目前的位置是在引擎的插件中。 Niagara在UE4开始就已经在构思做了,目的就是重构继承于UE3的Cascade。Niagara当时的设计目的就是data driven并且扩展性更高的粒子系统,解锁模拟和渲染,所以有图形化的节点能不需要程序来实现模拟的逻辑功能。所以2014年时引擎实现了向量化(指令并行)的虚拟机。 后续为了进一步提高了并行性,加入了compute shader的GPU支持。 本文主要设计Niagara 的主要代码框架结构,对其内部可能的其他一些知识体系。本接下来文章介绍Niagara 的编译和反射系统。因此本文就不在提及过多关于这方面的内容。 我们照例观察一下整个代码的文件组织。 Niagara:所有的运⾏和逻辑构成 。 NiagaraAnimNotifies:可以在动画的过程中进行事件通知播放Niagara。 NiagaraCore:⼀些通⽤的类 NiagaraEditor:编辑器内的可视化编辑节点。 NiagaraEditorWidgets:Niagara 的UI 。 NiagaraShader:Niagara 的shader 。 NiagaraVertexFactories:组成MeshBatch的顶点⼯⼚。 一.基本概念 1.1system 和Emitter 我们通常在编辑器中使用的是Niagara资源主要有两种,一种是我们的Niagara发射器Emitter,一种是我们的Niagara系统System。并且我们发射器是由我们的Module共同组成,从而完整的形成我们的整个Niagara系统。其设计理念相比与Cascade,拆分的更加的细致,从而能偶比较细致的组合和复用。 我们本次并不关心Module所能代表的发射和编译模块,我们重点关注的是Emitter和System所对应的运行时数据。 所有使用Niagara 的地方都需要我们的UNiagaraComponent来进行,其主要是进行控制和Niagara系统的交互。 我们在编辑器中资源对应的是UNiagaraSystem和UniagaraEmitter。一个UNiagaraComponent会拥有指定的一个UNiagaraSystem对应。但是UNiagaraSystem并不是我们运行时直接使用的数据。我们会在UNiagaraComponent初始化时构建对应UNiagaraSystem的FNiagaraSystemInstance,同样System里面的UNiagaraEmitter会生成对应的FNiagaraEmitterInstance。这如同类和实例的关系一般。 对于每个FSystemInstance,会有⼀个相对应这个System类型的的Simulation,它和Instance并不是⼀对⼀的 关系。如果场景中存在同⼀个UNiagaraSystem的多个实例,其只对应⼀个 FNiagaraSystemSimulation。也就是说,对于数据结构⼀致的实例,会使⽤同⼀个Simulation进⾏模拟。因为相同的System的Spawn和Update与数据存储的大小和类型是相同的。提高缓存一致性和数据的存储效率。 所有的FNiagaraSystemSimulation都由FNiagaraWorldManager统一进行管理。 1.2 运转流程 Niagara将有Initial和Update两个重要阶段。其中Initial只在一开始运行一次,Update则每帧运行。 而根据发生的位置不同分为SystemUpdate,EmitterUpdate和ParticleUpdate,分别代表每个System,每个Emitter,和每个粒子的更新。 例如我们spawn一个NiagaraActor,对应的NiagaraSystem中有两个Emitter,每个Emitter发射1000个粒子。 我们排除一些粒子间事件这种情况。那么当我们在初始化时,会调用一次SystemSpawn,调用各自的Emitter的EmitterSpawn,调用各自粒子的共两千次的ParticleSpawn。之后除非有新的Particle生成会调用particleSpawn,否则不会再调用任何Spawn。 之后,我们每帧都会调用我们的各种Update去更新数据。 1.3 渲染策略 这里忽略Light和component对应的Renderer。我们拥有多种渲染器可供选择。 我们其他MeshDraw一样会拥有⼀个渲染的代理Proxy帮助我们来完成最终的渲染,对于Component来说我们持有的该System 的所有Emiter带有的Renderer都会我们会赋值给Proxy。因此其实我们的最小MeshBatch单位是与Emitter数量相关,其数据被Proxy持有,最终交付渲染,这⾥的渲染和UE4普通的渲染架构并没有什么不同,都是统⼀的框架。 由于Niagara的可编程性,其实现功能的潜力是巨大的。它可以非常复杂,但是我们剖析其本质上是一种空间位置模拟的系统之后,我们就能够抓住其关键就是更新它需要的关键数据。更新FNiagaraDataSet。 二.模拟数据 不论Niagara Emitter有多少的Module,Module里有多少的脚本,脚本中写了多少东西。我们当然要抓住本质数据,其都是更新某个渲染器所需要的必要参数,也就是如下图所示的信息。 也就是说,只有这些信息是每个渲染器所需要的,其会传递给渲染线程并最终提交渲染。任何其他参数仅仅为中间变量。因此我们首先关心的是这个数据是存储在什么地方的。由于一个Emitter可以拥有多个不同的Renderer。因此其本身存储在Emitter级别,而不是在Renderer级别。 因此我们最终传递给渲染线程的数据存储在每个Emitter实例FNiagaraEmitterInstance的FNiagaraDataSet身上。不论是GPU粒子还是CPU粒子。 我们将FNiagaraDataSet的数据作为每帧更新的数据继续传递。FNiagaraDataSet最主要的数据是两个buffer。 其中一个是当前使用的buffer,一个是我们将要写入的buffer。FNiagaraDataBuffer拥有提供CPU粒子或者GPU粒子的数据。如果是CPU粒子,我们将在CPU做计算写入操作,如果是GPU粒子,我们在CPU端只需要把对应的buffer指定就可以了。 从传递的数据来看,如果我们是CPU粒子,将直接把最终的模拟结果对应的buffer传递给renderer。而GPU粒子则没有最终的数据,所以需要传递给渲染线程的数据则更完整一些。 其封装成FNiagaraComputeExecutionContext。 2.1 CPU粒子模拟数据更新 最开始我们有一个全局的管理器FNiagaraWorldManager。每一个System类型对应的唯一FNiagaraSystemSimulation都将在这里进行注册并且收到它的支配和管理。 我们的FNiagaraSystemSimulation的数据更新分成两个部分。 Tick_GameThread。这里主要是更新一下系统时间等参数,然后调用FNiagaraSystemInstance的Tick_GameThread。在FNiagaraSystemInstance主要是更新System的Parameters和DataInterface。 Tick_Concurrent,这个阶段可以不在Game线程完成。 对于那些新生成的SystemInstance调用它的spawn script。 是调用system update script进行System的更新。 将system模拟的结果注入到emitter的绑定数据中。 调用FNiagaraSystemInstance的Tick_Concurrent。 在FNiagaraEmitterInstance::PreTick中,最主要的是执行Emitter的Spawn和Update脚本。

给UE4项目改名

很多时候我们对一个工程随意地起了一个随意的名字,这很常见,如果我们想要后面修改整个项目的名字,似乎应该是一件简单的事情,但是这个过程充满了陷阱。如果做错了,您可能会无意间破坏您的项目。手动的做当然是一件非常困难的事情,尤其是对于C++的项目,其模块的命名其实并不容易进行修改,在这里介绍一个工具帮助我们自动的修改抿成。在进行这样的大更改之前,最好备份您的项目。当然,请确保重命名时未在编辑器中打开您的项目。 使用流程 我们打开二进制文件。 输入对应的目录:E:\UE4\1 需要注意的是,现在他没办法支持中文名称的更改 然后需要我们输入新的名称: 输入完成后就可以了。 其可处理蓝图和C++工程。 工程地址:https://github.com/UnrealisticDev/Renom 直接下载

UE4 一些实践建议

Interfaces优先于Cast。通常,我们将Actor或组件强制转换为能够访问其方法所需的Class类型,但是强制转换不仅在性能方面比Interfaces昂贵,而且实现起来也很烦人。尝试一下Interfaces。 使用组件共享行为。很多时候我们过多地依赖继承,以便在参与者之间共享行为。继承不一定全是错误的,但是比如游戏有两种类型的施加伤害的Actor:炮塔和角色。在这种情况下,您可以创建一个名为Damager的组件,并将其添加到两个Actor中。两个Actor都能够施加伤害,而不必担心他们是谁继承的。 隐藏对象的不可自定义属性。当Actor或Components具有变量时,您可以将它们从“详细信息窗格”中隐藏。只需单击要隐藏的变量,然后查找它们公开的“Advanced Display”属性并进行检查。之后,调整该Actor或Component或任何其他对象时,您将不再在“详细信息”窗格中看到此变量。 自动对齐连线。您创建了一个很棒的蓝图,里面到处都是节点。但是由于连线,它看起来像一团糟。快速改善这种情况的一件事是选择两个连接的节点并按“ Q”。 按Q前: 按Q后: 避免将持久状态存储在组件(Component)中。这更多地与有存档的游戏有关。无论使用哪种插件,还是想出自己的保存方法/解决方案,持久存储组件的变量都可能成为负担,因为大多数时候您必须在加载游戏之前重新创建组件并重新添加保存的组件。相反,应该将持久化变量(如HP、Money等)存储在Actors中。 尽可能使用球体而不是“胶囊和Box”。您有99%的时间希望在Actor中使用碰撞,而不必将它们设为Capsule或者Box。请改用Sphere,因为球的物理计算最简单。 使用数学表达式来描述您的数学公式。你可以像在论文中描述的那样描述它们!只需右键单击“蓝图”的网格,然后键入“添加数学表达式” 然后单击显示的选项。然后,像在纸上一样写下公式,并连接点! 8. 使用标签(Tags)!UE4为游戏中几乎每个对象都提供了一个被低估的内置功能,称为“Tags”。只需转到“对象详细信息/默认值”并搜索“标签”,就会显示一个数组。单击“加号”按钮并开始对其进行标记。这将很清楚的区分所有物体属性。当然,大型项目手动输入这些几乎是噩梦,小范围使用吧。 9. 不要滥用Event Tick。我知道这是陈词滥调,但这是严肃的事情。Event Tick是大多数问题的懒惰解决方案。假设您想在角色跳跃时做点什么。与其在事件Tick中放置“ if”以检查变量“ Is Jumping”是否为真,不如在按下按钮进行跳跃时创建一个名为“ OnCharacterJumpStart”(或任何您喜欢的事件)的事件分派器。然后,在对象处对跳转做一些事情。 你可能需要SetTimerByEvent而不是Event Tick。Event Tick在CPU的每一帧上运行。如果你需要以大于0.01s的时间间隔运行某项内容,则最好使用SetTimerByEvent。 在Replicated 事件(或RPC)中传递Actor是可行的。因为没办法传递一个Actor指针到服务器,Actor通过NetUID在RPC中传输,只有4个字节。然后,使用NetPackageMap将NetUID转换为指针,然后将其传递给对象。整个Actor仅发送一次。Actor的各个属性通过该Actor的ActorChannel更新。但是其他的指针,你最好想清楚。 使用SetGlobalTimeDilation。你是否知道在玩游戏时死亡或杀死某物时一切都会慢动作如何做到的?好吧,这是您执行此操作的方法之一。 经常打包游戏。“我希望我早点知道”这件事。你在打包时可能会面临噩梦,这是构建时在开发时看不到的一大堆错误。您等待的打包时间越长,发生错误的机会就越大。因此,请经常打包,经常解决问题,并保持整洁和安全。 在蓝图里使用Ctrl + Shift + F查找所需内容。

UE4 主渲染函数

从今天起,我将从主渲染函数入手,来整理整个UE4的渲染内容和框架,这将是一个非常漫长和艰巨的任务,因为其内容实在是太多,虚幻的更新速度也是超乎寻常的快,但是以后的版本应该不会有大的调整,毕竟新的框架直接用在UE5就可以了。 这里我们只是笼统的将Render函数那一个层级所出现的内容进行概况和整理,每一个概念的内部原理将会在之后的该系列文章中进行讲解。 虚化中目前的渲染基类为FSceneRenderer,其一共有两个派生类,一个是FDeferredShadingSceneRenderer,另一个是FMobileSceneRenderer。当然我们就算是在编辑器里选择为前向渲染,其本身还是会走FDeferredShadingSceneRenderer,FMobileSceneRenderer确实是移动平台才会创建的类型。我们讲讨论feature更完备的FDeferredShadingSceneRenderer。 关于延迟渲染和前向渲染这种问题到底还需不需要讨论,如果有讨论的必要请在评论区留言,否则就默认大家都会的。因为实在是没办法照顾到所有人的学习阶段,是统一天坑还是我讲我的,前期很多概念没有达成共识的话,基本上很难理解剩下的内容。 在这里我将去掉与头发、光线追踪,虚拟纹理相关内容,因为他们比较凌乱,后面如果有可能会出专题。 看代码之前我们可以使用RenderDoc来抓帧unreal,只要安装了RenderDoc并且你启用了对应的插件。之后你就会看到对应的渲染列表。 这可以帮助你快速的对应代码,图形化的帮助你理解每一步的用处。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 //更新需要添加到scene和需要删除的物体。 Scene->UpdateAllPrimitiveSceneInfos(RHICmdList, true); //抗锯齿策略,分辨率大小比例,窗口大小,屏幕百分比策略 PrepareViewRectsForRendering(); //场景中是否存在天空大气的渲染需求,进行准备工作 PrepareSunLightProxy(*Scene->GetSkyAtmosphereSceneInfo(),LightIndex, *Scene->AtmosphereLights[LightIndex]); //如果存在多GPU,计算GPUMask ComputeViewGPUMasks(RenderTargetGPUMask); //将RT池中的rt设置为可写入 GRenderTargetPool.

100TipForUnreal

1.Paste Here(复制到这个位置) 我们打开编辑器的设置,然后可以设置这个快捷键,例如我们可以设置为左括号 之后我们在场景中复制的时候,就可以直接使用这个快捷键,将之前你Ctrl C的东西复制到你鼠标的位置。 2. 快速对齐——按住V键拖动物体顶点对齐 我们在拖动一个物体的时候,按住V键,可以显示它周围的物体的顶点并且在移动的时候吸附上去。场景摆放的时候利器!。 3. 鼠标中键移动物体中心 我们知道所有的物体中心是制作模型的时候决定的,但是我们在编辑器摆放物体的时候,希望能够边缘点对齐,我们就可以临时移动中心点。当然这个移动后中心点是临时的,不会保存。 4. 自定义项目类别 我们可以通过修改.uproject file的category来实现 5. 使用高级的文件检索方式 例如我们所有定点数小于1000的模型 6. 输入计算 7.选择log类型 8. 修改文件夹颜色 可以自定义颜色,明显的标记出自己常用的文件夹 9.修改缩略图 我们可以转动编辑器里面的缩略图,进行更改 10.Ctrl +鼠标中间+ 拖动 =快速切换视图 我们使用Ctrl +鼠标中间+ 拖动可以快速切换视图,拖动的方向决定你的视图模式。 11.测量距离 在平行投影的视图中使用鼠标中键可以测试距离,单位是厘米。 12.你可以打开4个Content 这样你就不用每次翻阅资源都跳转了,你需要提前锁住。 13.你可以打开4个Detail面板 14.你可以复制任意属性 15.你在编辑器复制的所有东西,其实都文本 所以我们是可以直接使用文本传递的。 推荐的网站https://blueprintue.com/,可以共享蓝图。 16. 你能够在color picker保存颜色 17.你能够任意拖动数组改变里面的位置 18.蓝图全搜索 使用CTRL + SHIFT + F 在蓝图编辑器中 19. 使用Ctrl 移动节点 20. 修改网络样式 1 2 3 r.Editor.NewLevelGrid 0 r.Editor.NewLevelGrid 1 r.Editor.NewLevelGrid 2 21.

UE4网络教程1-网络架构总揽

一.网络总览 Unreal Engine4使用标准的Server-Client体系结构。 这意味着服务器是权威的,所有数据必须首先从客户端发送到服务器。 然后服务器依赖你写的代码验证数据并且给予反馈。 1.1一个简单的例子 在多人匹配中,作为一个客户端,当你移动你的角色时,你并不是自己移动你的角色,而是告诉服务器你想移动它。 然后服务器为其他人(包括你)更新你的位置,。 注意:为了防止对本地客户端产生“滞后”的感觉,程序员经常让这个玩家直接在本地控制他们的角色,虽然服务器仍然可能在客户端开始作弊的时候覆盖角色的位置!这意味着,客户端将(几乎)永远不会直接与其他客户端“交谈”。 1.2其他的例子 当向另一个客户端发送聊天消息时,您实际上是将其发送到服务器,然后服务器将其传递给您想要到达的客户端。 也许你消息的结构方并不是一个人,也就是不只是一次私聊,对方有可能是是一个team,guild,group等。 永远不要相信客户! 信任客户端意味着在执行客户端操作之前不测试客户端操作。 这将允许作弊!不过有些情况下我们可能会允许一些纯粹表现的效果只在客户端进行而不在客户端验证。一个简单的例子是射击:在服务器上应当确保对某个客户端的测试,如果在服务器的记录中显示该客户端实际上有弹药,才应当允许该客户端射击,而不是直接在客户端处理射击! 二.UE4 的网络框架 我们如果拥有一个对象,使用前面关于UE4的Server-Client体系结构的信息,我们可以将框架分成4个部分: Server Only – 只在服务器上 Server & Clients – 同时存在客户端和服务器 Server & Owning Client – 只在服务器和拥有他的客户端上 Owning Client Only – 这些对象只存在于客户端上 “Owning Client”是一个所有权的问题,也就是这个对象的所有权是否是在你这一台客户端上,例如你控制的角色,这个对象对于你来说,归属权就是Owning Client。 所有权在以后的“RPC”中变得很重要。下图展示了一些常见的类以及它们存在的部分。这就是一些最重要的类是如何在网络框架中布局的。 下图显示了另一个例子(具有两个客户端的专用服务器),说明这些类的对象如何通过网络框架分发: 之后将展示一些最常见的类。 还将提供如何使用这些类的小示例。 如果不理解,请忽略,直到您阅读系列后面有关复制等章节的内容。 一些游戏类型可能会使用不同方式使用这些类。 下面的例子和解释不是唯一的方法 2.1 GameMode 4.14开始GameMode类被分成 GameModeBase和GameMode。 GameModeBase的功能较少,因为有些游戏可能不需要GameModeBase类的完整功能。 GameMode用于定义游戏的规则。 这包括如Apawn、Player Controller、APlayer State等。 它只在服务器上可用。 客户端没有这个对象,并且在试图检索它时只会得到一个nullptr。 GameMode例如死亡匹配,团队死亡匹配或捕获旗帜等模式。这意味着游戏模式可以定义如下内容: