游戏开发中的预览


在游戏开发过程中,对角色的预览,和某些情况下生成头像是比较常见的需求。有些引擎,可以创建一个额外的场景和相机,然后将需要的内容放置到合适的位置,然后可以获得想要的图像。在UE4中不是这样,没法创建其他的场景,我们需要使用CaptureSceneComponent2D,字面意思看出来这是个场景捕获的组件,它就是用来捕获我们想要的场景内容到2D图像上。

CaptureSceneComponent2D如何使用


这个组件的使用相当简单,首先我们新建一个第三人称的示例工程,使用以下基本步骤:

  1. 创建RenderTarget2D,捕获组件捕获的内容需要渲染到这个纹理上。选择AddNew->Materials & Textures -> RenderTarget来创建,并命名为 RT_Preview。

  1. 在场景中放入SceneCapture2D,调整位置和朝向,对着角色


  1. 选中场景中的SceneCapture2D对象,查看Details面板,找到TextureTarget项,然后选择刚刚创建的RT_Preview,选择之后立刻就会发现其中的小预览图就变成场景中的样子。

对,就是这么简单,这个时候我们已经得到了一张捕获的纹理。那么这个纹理如何使用呢?可以跟普通的贴图一样使用,不过稍微有一点点区别,这个稍后再说。

使用RenderTarget2D


为了使用刚刚捕获的图像,我们可以建立一个界面来展示它。

  1. 创建一个界面蓝图,并放上一个图像控件,并设置图像控件Brush中的图片为之前的RT_Preview,然后在关卡蓝图里面,设置一个按键响应,把这个界面给展示出来。这里选择F键。

  2. 运行游戏之后,按F键,发现界面上啥也没有。原来RenderTarget纹理的透明度比较特别(具体是怎样还没有研究),我们回到场景,再次选中SceneCapture2D对象,在Details面板找到Catpture Source选项,然后选择如下。再次运行我们就可以看到界面中的图像。


只捕获想要获取的对象


从上面的截图可以看出来,角色背后的蓝天及场景中的其他内容都被捕获了。在实际应用中,这些部分一般来说是不需要的。那么如何设置只捕获特定内容呢?

  1. 依然是SceneCapture2D对象,它的属性中有个参数叫Primitive Render Mode, 这个就是用来控制绘制内容模式的,它有个叫做Use ShowOnly List的模式,这个模式就可以指定一些对象,然后只捕获这部分内容。

    使用这个模式的一个小问题是,如果在编辑器中直接选择这个选项,那么TextureTarget中的预览将会消失。所以我们在编辑器中不修改它的模式,而在蓝图中动态设置。

  1. 打开场景蓝图,在F按键之后的代码加上SceneCapture2D的一些设置


结果如下:可以看到场景部分都消失了,不过还有蓝的白的背景在。这部分内容应该是属于透明内容。下一节我们再把它给去除掉。在这里我们使用了Show Only ActorComponents 即只捕获特定的Actor对象,也可以使用Show Only Components节点来添加指定的组件,可以做到比Actor更细化的控制。后面还会讲到。

去除不透明的背景,创建UI材质

  1. 前面有讲到将CaptureSource给设置成了Final Color(LDR) in RGB,这个设置实际上是将Alpha属性给丢了,所以我们首先将这个属性重新设置为第一项:

  1. 创建一个材质, 命名为 MT_Preview,并打开。

    • 把MaterialDomain设置为User Interface,因为这个才是是给UI用的
    • 把BlendMode设置Translucent因为我们需要透明属性
    • 把之前建的RT_Preview拖入图表中,按如图连线
    • 1-x节点叫 OneMinus

  1. 回到界面蓝图,之前图片的Image选择的是RT_Preview,是直接使用的纹理,现在改成MT_Preview,使用新建的材质。

  2. 再次运行游戏,按F键可以看到如下画面,背景中的蓝白色已经去除了。

到了这里,我们捕获的内容基本上已经符合了预期:

  • 只捕获特定的角色
  • 背景是透明的,便于在界面上显示

然而,它还不能正直使用在游戏中,为什么?

改进


目前我们捕获的对象是场景中的玩家对象,玩家对象会移动,一旦移动我们就捕获不到了。这个问题有两个解决方法,

  • 第一个是可以把捕获控件绑在玩家身上,跟着玩家一起动。这个方案也还有问题,那就是玩家会播很多动作,可能并不是你想要捕获的,除了特殊使用目的,不建议使用。
  • 创建一个专门的捕获Actor,在其中放入特定的Mesh,然后捕获组件只捕获自己Actor中的指定Mesh或者特定Actor。此方案需要管理一个临时Actor。

接下来就以第二个方案来简述实际操作。

  1. 创建Preview的Actor:创建一个蓝图,继承Actor,命名为A_Capture_Preview。并添加SceneCaptureComponent2D组件和SkeltalMesh组件。SceneCaptureComponent2D设置TextureTarget为RT_Preview,SkeltalMesh的Mesh设置为SK_Mannequin,并调整位置和朝向如下图所示


  1. 去除之前场景中添加的那个SceneCapture2D对象,我们使用动态创建的方法来构建Preview Actor。首先在A_Capture_Preview的BeginPlay中设置只捕获自己的本身

  1. 然后我们修改一下Level Blueprint,创建这个捕获Actor,CollisionHandlingOverride可以选择AlwaysSpawn,避免因为某些原因创建失败。

  1. 运行游戏,按F键,可以看到界面跟之前展示的一样,不同的是:

    • 玩家走动,不会影响界面

    • 场景中多了一个模型,这是我们SpawnActor引入的一个模型

我们SpawnActor只是为了用于捕获,不希望主摄像机可以看到,那么这里又有两个方法:

  • 把临时Actor放远一点(这个方案有些意外的效果,后面再说)
  • 让主摄像机看不到这个临时Actor

我们先来说第二中方案,如何让主摄像机屏蔽或者说过滤掉我们得临时Actor。首先打开ACapturePreview蓝图,选中SkeletalMesh,然后在细节面板上找到Renderring选项卡,点击下面的三角形展开高级选项,如下图:

这里有两个选项,Owner No See(拥有者不可见) Only Owner See(仅拥有者可见) ,利用Owner No See这个选项,再把临时对象的Owner设置成主角Actor,那么主角就看不到这个临时Actor了(对于网络游戏,在客户端创建的临时Actor,其他人本来就看不见,所以也不用担心。)

  • 勾选Owner No See

  • 在Spawn之后,将Owner设置成主角Character

再次运行游戏,按F之后,已经看不到临时对象了,界面表现则是和之前一样。

这里可能有人要问了,为什么不选择OnlyOwnerSee,然后把Owner设置成自己呢?这里的问题是Owner不能设置成自己,如果要选择OnlyOwnerSee,则必须将模型与SceneCaptureComponent拆成2个Actor来实现,这也是个方法,但是需要管理两个临时对象,具体的实现就大家自行实现吧。

为什么不把临时Actor放远一点来拍摄?


在一定程度上来说,没啥问题,但是如果Actor离主相机太远,引擎会对Actor进行优化,导致捕获的效果非常糟糕,一方面是LOD的原因,一方面未启用LOD的情况下,离的足够用,也会强制优化。


不断的将距离设置的更大之后,可以发现界面上的效果越来越差,直到不能接受。最后一项Actor离主角的距离是40000000。当然你可能不会设置那么远,只要找一个合适的位置让玩家当前看不到他就是可以接受的。如果你发现界面上的效果达不到预期的时候,就要考虑是否因为距离过大导致的。

另外,也是接下来要讲的,使用正交投影来获取2D头像的时候,对距离比透视投影要敏感非常多,距离设置到10000就有明显的区别。


所以推荐的做法是前面说的那种,将临时对象放在离主角比较近的地方,但让主角看不到他。

2D头像的获取


3D预览使用透视投影,2D头像由于离的非常近,如果继续使用透视投影,很容易出现比例不协调的问题,比如鼻子可能非常大,其他部位特别小,不符合要求。

这个时候就要使用正交投影,继续使用刚刚的ACapturePreview对象,选中SceneCaptureComponent2D组件,找到Projection选项卡,ProjectionType选择Orthographic,选择之后OrthoWidth变得可用,这个选项类似Field,越大则范围越大,越小则范围越小。在这个模式下,相机的远近不会改变捕获的范围,需要修改OrthoWidth才有效果。例如下面的选项,设置为50,可以看到TextureTarget部分的预览。

注意红框中的两个选项,PrimitiveRenderMode在前面有提到,为了方便在未运行时预览TextureTarget,这里不做修改,使用蓝图代码在运行时修改模式为ShowOnlyListCaptureEveryFrame是每帧捕获的意思,可想而知这个选项会带来相当的消耗。对于2D头像来说,是静态的,只需要捕获一帧就可以了,所以这里取消勾选。

2D头像在3D的基础上只是两点不同:

  • 投影方式修改
  • 去除CaptureEveryFrame

接下来,探讨个稍微复杂点的情况。通过上面的介绍大家基本上明白了,捕获的基本流程:

  • 创建RenderTarget
  • 创建使用RenderTarget的材质
  • 界面图像使用指定材质
  • 创建临时Actor,捕获图像,更新RenderTarget

这个过程中,我们创建了一个RenderTarget,一个材质,一个临时对象。如果我们在游戏中需要同时显示多个动态捕获的头像怎么办?那就得创建N个RenderTarget,N个材质,N个临时对象?下面就来介绍一种全动态RenderTarget+材质的创建方案,对于捕获Actor,如果各个需要的场景对镜头没有区分要求,那其实可以使用同一个,然后动态的修改SkeletonMesh就可以。

全动态生成2D头像


  1. 首先我们还是得手动创建一个RenderTarget,这个RenderTarget仅用于在编辑器中预览使用,可以继续使用前面的RT_Preview。材质也可以继续使用MT_Preview,但是需要稍作修改,在材质中的TextureSample节点上右键,并选择ConvertToParameter , 这个时候可以在左侧ParameterName出修改参数的名称,这个名称记下来,后面动态设置的时候会用到。


  1. 打开WBP_Head蓝图,新建函数UpdateImgMat,新增Input参数,类型选择为Material Instance Dynamic, 并命名为 ImgMat

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LqmuSM9B-1586704838239)(image-20200412223739043.png)]

并实现函数,此函数可以让我们使用动态材质来填充图像。

  1. 打开Level Blueprint,新建一个函数CreateDynamicHead ,这个函数建在哪里不重要,只要有合适的时机即可

这三个节点,首先创建一个RenderTarget2D ,然后根据MT_Preview来创建一个动态材质示例,第三个节点就是把前面的RenderTarget2D传递给材质的MainTex参数。这就是我们第一步把材质中的纹理提升为参数的目的。实际上动态材质的核心就是上面三个节点,接下来需要做两件事:

  • 把材质传递给界面控件
  • 把RenderTarget传递给捕获Actor

界面已经提供了接口,调用一下即可,ACapturePreview也需要提供一个接口来接受RenderTarget数据。

  1. 打开ACapturePreview,新建函数SetRenderTarget,新建参数RenderTarget,类型为TextureRenderTarget2D

函数内容也很简单

接下来就是稍微改造一下Level Blueprint中的函数CreateDynamicHead 分成四个步骤:

  • 创建界面

  • 创建临时Capture对象

  • 创建动态的RenderTarget及材质

  • 将材质传递给界面对象,将RenderTarget传递给Catpture对象

按键F的响应则只需要直接调用该函数

按F运行游戏,发现头像跟之前没有任何的区别。

没有区别就对了,这里只是展示一种动态构建的方法,效果并没有改变。对于界面上多个头像的展示,跟前面的代码结构类似,不同的界面,使用不同的预览对象,自行设置就好。由于大家各自使用的RenderTarget和材质都是动态的,所以不会相互干扰,这是主要目的。

UE4 角色预览与头像生成 CaptureSceneComponent2D 看这一篇就够了相关推荐

  1. UE4.18预览第一版发布,共享XR引擎层降低硬件支持难度

    (52VR.com优质翻译) 作为Unreal Engine 4的常规更新,9月22日Epic Games发布了Unreal Engine 4.18版本的第一个预览版,其中包括对iOS 11和增强现实 ...

  2. dnf时装预览怎么打开_您看我还有机会吗?被阉割的DNF时装市场系统

    在DNF​100级更新之后,韩服同步更新了时装市场系统. 但这一系统在国服却惨遭阉割,并没有跟随100级版本的脚步一并实装到国服. 先让我们回顾一下,这个时装市场是怎么一回事. [入场条件] *在西海 ...

  3. 划重点!Android 11 首个开发者预览版新功能抢先看

    5G支持引领了Google移动操作系统面向开发人员的新功能.Android 11中为应用程序开发人员提供了许多新工具,但我们必须等到今年晚些时候才能看到面向用户的变化. -- Michael Much ...

  4. uni-app实现PDF预览功能(避坑看这)

    目录 前言 一.下载PDF预览相关文件 二.使用步骤 前言 去年就想写一篇关于uni-app的pdf预览功能,拖很久了,补上. 一.下载PDF预览相关文件 下载地址 解压后效果: 二.使用步骤 在  ...

  5. Android多种方式实现相机圆形预览 看这一篇就够了,Android开发面试书籍

    } public void turnRound() { invalidateOutline(); } 即可根据设置的圆角值更新控件显示的圆角大小.当控件为正方形,且圆角值为边长的一半,显示的就是圆形. ...

  6. 设置webstorm实时预览看这一篇就够了,5分钟解决!!

    1.安装插件Live Edit 这里学到了一个名词,捆绑,意思就是有的编辑器默认自带的,无须另外下载我这里是2020.3.2是自带的,检查是不是自带的也很简单,按照下图去看看是不是有Live Edit ...

  7. 计算机目录排版的文章,自动生成目录,论文排版看这一篇就够了

    很多同学写论文时候,对于排版比较纠结.一般各大高校对版面要求都大同小异,下面塔尖君就给大家介绍一下,论文排版的注意事项: 自动生成目录 因为本人使用的是wps软件,而不是word.主要原因是wps体积 ...

  8. [Golang梦工厂]一个小项目带你学会GIN框架、JWT鉴权、swagger生成接口文档,看这一篇就够了

    前言 哈喽,大家好,我是asong,这是我的第八篇原创文章.听说你们还不会jwt.swagger,所以我带来一个入门级别的小项目.实现用户登陆.修改密码的操作.使用GIN(后台回复Golang梦工厂: ...

  9. [Unity2D]角色卡墙上?角色摩擦力改为0后一直移动?看这一篇就够了

    相信点进来的都是因为发现角色一直向前移动会粘在墙上,这种情况一般给 角色的碰撞上一个无擦的材质就行了 但是这样做了之后会发现角色移动一下会一直向前不停移动 这是因为 角色的线性阻力可能为0,这个值设置 ...

最新文章

  1. map multimapc++_C++的Map和Multimap
  2. drtek收音机使用说明_一百年前的便携式矿石收音机长啥样?这台1919年产品给你答案...
  3. java线程的基本概念
  4. 网络通信-2(TCP通信、ServerSocket、Socket)
  5. MySQL 数据库中如何将表字段的空值全部替换成空字符串
  6. python变量名称的规定_Python 趣闻:如何获得变量的名字?
  7. 240多个jQuey插件
  8. 20140704笔试面试总结(java)
  9. 软件测试总结--02缺陷报告
  10. csu 1196 - 去爬山
  11. 微信 原创保护开通申请协议内容
  12. 做企业管理软件的,怎能不读这本1965年的书呢?
  13. 很多次游戏的最后取胜实际上都有很强的偶然性
  14. flex布局实现骰子六面的示例
  15. 共享打印机无法打印问题解决
  16. Web系统大规模并发——电商秒杀与抢购
  17. python 编程4,和7 幸运数字
  18. 无人驾驶汽车路径规划概述
  19. 机器学习十大算法的简单介绍
  20. 是什么,让你过上痛苦又低配的生活?

热门文章

  1. linux media 权限,root用户在media文件夹下修改文件权限无效
  2. 论PM所指的两个职位
  3. 计算机被限制压缩包打不开怎么办,压缩文件打不开,教您压缩文件打不开怎么办解决...
  4. matlab压缩包提示无法打开,压缩包打不开怎么办-解决压缩文件无法打开的方法 - 河东软件园...
  5. 数据安全类课程有哪些?DSO-DCO-DSP
  6. 蓝桥杯 算法训练 无聊的逗 python
  7. 如何配置使用 Log4j
  8. NLP基础:情感分析
  9. 重磅!ChatGPT 网页版来啦!响应速度超快!
  10. JS之判断是否为数组的方法