UE4 角色预览与头像生成 CaptureSceneComponent2D 看这一篇就够了
游戏开发中的预览
在游戏开发过程中,对角色的预览,和某些情况下生成头像是比较常见的需求。有些引擎,可以创建一个额外的场景和相机,然后将需要的内容放置到合适的位置,然后可以获得想要的图像。在UE4中不是这样,没法创建其他的场景,我们需要使用CaptureSceneComponent2D,字面意思看出来这是个场景捕获的组件,它就是用来捕获我们想要的场景内容到2D图像上。
CaptureSceneComponent2D如何使用
这个组件的使用相当简单,首先我们新建一个第三人称的示例工程,使用以下基本步骤:
- 创建RenderTarget2D,捕获组件捕获的内容需要渲染到这个纹理上。选择AddNew->Materials & Textures -> RenderTarget来创建,并命名为 RT_Preview。
- 在场景中放入SceneCapture2D,调整位置和朝向,对着角色
- 选中场景中的SceneCapture2D对象,查看Details面板,找到TextureTarget项,然后选择刚刚创建的RT_Preview,选择之后立刻就会发现其中的小预览图就变成场景中的样子。
对,就是这么简单,这个时候我们已经得到了一张捕获的纹理。那么这个纹理如何使用呢?可以跟普通的贴图一样使用,不过稍微有一点点区别,这个稍后再说。
使用RenderTarget2D
为了使用刚刚捕获的图像,我们可以建立一个界面来展示它。
创建一个界面蓝图,并放上一个图像控件,并设置图像控件Brush中的图片为之前的RT_Preview,然后在关卡蓝图里面,设置一个按键响应,把这个界面给展示出来。这里选择F键。
运行游戏之后,按F键,发现界面上啥也没有。原来RenderTarget纹理的透明度比较特别(具体是怎样还没有研究),我们回到场景,再次选中SceneCapture2D对象,在Details面板找到
Catpture Source
选项,然后选择如下。再次运行我们就可以看到界面中的图像。
只捕获想要获取的对象
从上面的截图可以看出来,角色背后的蓝天及场景中的其他内容都被捕获了。在实际应用中,这些部分一般来说是不需要的。那么如何设置只捕获特定内容呢?
依然是SceneCapture2D对象,它的属性中有个参数叫
Primitive Render Mode
, 这个就是用来控制绘制内容模式的,它有个叫做Use ShowOnly List
的模式,这个模式就可以指定一些对象,然后只捕获这部分内容。使用这个模式的一个小问题是,如果在编辑器中直接选择这个选项,那么TextureTarget中的预览将会消失。所以我们在编辑器中不修改它的模式,而在蓝图中动态设置。
- 打开场景蓝图,在F按键之后的代码加上SceneCapture2D的一些设置
结果如下:可以看到场景部分都消失了,不过还有蓝的白的背景在。这部分内容应该是属于透明内容。下一节我们再把它给去除掉。在这里我们使用了Show Only ActorComponents
即只捕获特定的Actor对象,也可以使用Show Only Components
节点来添加指定的组件,可以做到比Actor更细化的控制。后面还会讲到。
去除不透明的背景,创建UI材质
- 前面有讲到将CaptureSource给设置成了
Final Color(LDR) in RGB
,这个设置实际上是将Alpha属性给丢了,所以我们首先将这个属性重新设置为第一项:
- 创建一个材质, 命名为 MT_Preview,并打开。
- 把MaterialDomain设置为User Interface,因为这个才是是给UI用的
- 把BlendMode设置Translucent因为我们需要透明属性
- 把之前建的RT_Preview拖入图表中,按如图连线
- 1-x节点叫 OneMinus
回到界面蓝图,之前图片的Image选择的是RT_Preview,是直接使用的纹理,现在改成MT_Preview,使用新建的材质。
再次运行游戏,按F键可以看到如下画面,背景中的蓝白色已经去除了。
到了这里,我们捕获的内容基本上已经符合了预期:
- 只捕获特定的角色
- 背景是透明的,便于在界面上显示
然而,它还不能正直使用在游戏中,为什么?
改进
目前我们捕获的对象是场景中的玩家对象,玩家对象会移动,一旦移动我们就捕获不到了。这个问题有两个解决方法,
- 第一个是可以把捕获控件绑在玩家身上,跟着玩家一起动。这个方案也还有问题,那就是玩家会播很多动作,可能并不是你想要捕获的,除了特殊使用目的,不建议使用。
- 创建一个专门的捕获Actor,在其中放入特定的Mesh,然后捕获组件只捕获自己Actor中的指定Mesh或者特定Actor。此方案需要管理一个临时Actor。
接下来就以第二个方案来简述实际操作。
- 创建Preview的Actor:创建一个蓝图,继承Actor,命名为A_Capture_Preview。并添加SceneCaptureComponent2D组件和SkeltalMesh组件。SceneCaptureComponent2D设置TextureTarget为RT_Preview,SkeltalMesh的Mesh设置为SK_Mannequin,并调整位置和朝向如下图所示
- 去除之前场景中添加的那个SceneCapture2D对象,我们使用动态创建的方法来构建Preview Actor。首先在A_Capture_Preview的BeginPlay中设置只捕获自己的本身
- 然后我们修改一下Level Blueprint,创建这个捕获Actor,CollisionHandlingOverride可以选择AlwaysSpawn,避免因为某些原因创建失败。
运行游戏,按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,这里不做修改,使用蓝图代码在运行时修改模式为ShowOnlyList
。CaptureEveryFrame
是每帧捕获的意思,可想而知这个选项会带来相当的消耗。对于2D头像来说,是静态的,只需要捕获一帧就可以了,所以这里取消勾选。
2D头像在3D的基础上只是两点不同:
- 投影方式修改
- 去除CaptureEveryFrame
接下来,探讨个稍微复杂点的情况。通过上面的介绍大家基本上明白了,捕获的基本流程:
- 创建RenderTarget
- 创建使用RenderTarget的材质
- 界面图像使用指定材质
- 创建临时Actor,捕获图像,更新RenderTarget
这个过程中,我们创建了一个RenderTarget,一个材质,一个临时对象。如果我们在游戏中需要同时显示多个动态捕获的头像怎么办?那就得创建N个RenderTarget,N个材质,N个临时对象?下面就来介绍一种全动态RenderTarget+材质的创建方案,对于捕获Actor,如果各个需要的场景对镜头没有区分要求,那其实可以使用同一个,然后动态的修改SkeletonMesh就可以。
全动态生成2D头像
- 首先我们还是得手动创建一个RenderTarget,这个RenderTarget仅用于在编辑器中预览使用,可以继续使用前面的RT_Preview。材质也可以继续使用MT_Preview,但是需要稍作修改,在材质中的TextureSample节点上右键,并选择
ConvertToParameter
, 这个时候可以在左侧ParameterName出修改参数的名称,这个名称记下来,后面动态设置的时候会用到。
打开WBP_Head蓝图,新建函数
UpdateImgMat
,新增Input参数,类型选择为Material Instance Dynamic, 并命名为 ImgMat[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LqmuSM9B-1586704838239)(image-20200412223739043.png)]
并实现函数,此函数可以让我们使用动态材质来填充图像。
- 打开Level Blueprint,新建一个函数
CreateDynamicHead
,这个函数建在哪里不重要,只要有合适的时机即可
这三个节点,首先创建一个RenderTarget2D ,然后根据MT_Preview来创建一个动态材质示例,第三个节点就是把前面的RenderTarget2D传递给材质的MainTex参数。这就是我们第一步把材质中的纹理提升为参数的目的。实际上动态材质的核心就是上面三个节点,接下来需要做两件事:
- 把材质传递给界面控件
- 把RenderTarget传递给捕获Actor
界面已经提供了接口,调用一下即可,ACapturePreview也需要提供一个接口来接受RenderTarget数据。
- 打开ACapturePreview,新建函数SetRenderTarget,新建参数RenderTarget,类型为
TextureRenderTarget2D
。
函数内容也很简单
接下来就是稍微改造一下Level Blueprint中的函数CreateDynamicHead
分成四个步骤:
创建界面
创建临时Capture对象
创建动态的RenderTarget及材质
将材质传递给界面对象,将RenderTarget传递给Catpture对象
按键F的响应则只需要直接调用该函数
按F运行游戏,发现头像跟之前没有任何的区别。
没有区别就对了,这里只是展示一种动态构建的方法,效果并没有改变。对于界面上多个头像的展示,跟前面的代码结构类似,不同的界面,使用不同的预览对象,自行设置就好。由于大家各自使用的RenderTarget和材质都是动态的,所以不会相互干扰,这是主要目的。
UE4 角色预览与头像生成 CaptureSceneComponent2D 看这一篇就够了相关推荐
- UE4.18预览第一版发布,共享XR引擎层降低硬件支持难度
(52VR.com优质翻译) 作为Unreal Engine 4的常规更新,9月22日Epic Games发布了Unreal Engine 4.18版本的第一个预览版,其中包括对iOS 11和增强现实 ...
- dnf时装预览怎么打开_您看我还有机会吗?被阉割的DNF时装市场系统
在DNF100级更新之后,韩服同步更新了时装市场系统. 但这一系统在国服却惨遭阉割,并没有跟随100级版本的脚步一并实装到国服. 先让我们回顾一下,这个时装市场是怎么一回事. [入场条件] *在西海 ...
- 划重点!Android 11 首个开发者预览版新功能抢先看
5G支持引领了Google移动操作系统面向开发人员的新功能.Android 11中为应用程序开发人员提供了许多新工具,但我们必须等到今年晚些时候才能看到面向用户的变化. -- Michael Much ...
- uni-app实现PDF预览功能(避坑看这)
目录 前言 一.下载PDF预览相关文件 二.使用步骤 前言 去年就想写一篇关于uni-app的pdf预览功能,拖很久了,补上. 一.下载PDF预览相关文件 下载地址 解压后效果: 二.使用步骤 在 ...
- Android多种方式实现相机圆形预览 看这一篇就够了,Android开发面试书籍
} public void turnRound() { invalidateOutline(); } 即可根据设置的圆角值更新控件显示的圆角大小.当控件为正方形,且圆角值为边长的一半,显示的就是圆形. ...
- 设置webstorm实时预览看这一篇就够了,5分钟解决!!
1.安装插件Live Edit 这里学到了一个名词,捆绑,意思就是有的编辑器默认自带的,无须另外下载我这里是2020.3.2是自带的,检查是不是自带的也很简单,按照下图去看看是不是有Live Edit ...
- 计算机目录排版的文章,自动生成目录,论文排版看这一篇就够了
很多同学写论文时候,对于排版比较纠结.一般各大高校对版面要求都大同小异,下面塔尖君就给大家介绍一下,论文排版的注意事项: 自动生成目录 因为本人使用的是wps软件,而不是word.主要原因是wps体积 ...
- [Golang梦工厂]一个小项目带你学会GIN框架、JWT鉴权、swagger生成接口文档,看这一篇就够了
前言 哈喽,大家好,我是asong,这是我的第八篇原创文章.听说你们还不会jwt.swagger,所以我带来一个入门级别的小项目.实现用户登陆.修改密码的操作.使用GIN(后台回复Golang梦工厂: ...
- [Unity2D]角色卡墙上?角色摩擦力改为0后一直移动?看这一篇就够了
相信点进来的都是因为发现角色一直向前移动会粘在墙上,这种情况一般给 角色的碰撞上一个无擦的材质就行了 但是这样做了之后会发现角色移动一下会一直向前不停移动 这是因为 角色的线性阻力可能为0,这个值设置 ...
最新文章
- map multimapc++_C++的Map和Multimap
- drtek收音机使用说明_一百年前的便携式矿石收音机长啥样?这台1919年产品给你答案...
- java线程的基本概念
- 网络通信-2(TCP通信、ServerSocket、Socket)
- MySQL 数据库中如何将表字段的空值全部替换成空字符串
- python变量名称的规定_Python 趣闻:如何获得变量的名字?
- 240多个jQuey插件
- 20140704笔试面试总结(java)
- 软件测试总结--02缺陷报告
- csu 1196 - 去爬山
- 微信 原创保护开通申请协议内容
- 做企业管理软件的,怎能不读这本1965年的书呢?
- 很多次游戏的最后取胜实际上都有很强的偶然性
- flex布局实现骰子六面的示例
- 共享打印机无法打印问题解决
- Web系统大规模并发——电商秒杀与抢购
- python 编程4,和7 幸运数字
- 无人驾驶汽车路径规划概述
- 机器学习十大算法的简单介绍
- 是什么,让你过上痛苦又低配的生活?
热门文章
- linux media 权限,root用户在media文件夹下修改文件权限无效
- 论PM所指的两个职位
- 计算机被限制压缩包打不开怎么办,压缩文件打不开,教您压缩文件打不开怎么办解决...
- matlab压缩包提示无法打开,压缩包打不开怎么办-解决压缩文件无法打开的方法 - 河东软件园...
- 数据安全类课程有哪些?DSO-DCO-DSP
- 蓝桥杯 算法训练 无聊的逗 python
- 如何配置使用 Log4j
- NLP基础:情感分析
- 重磅!ChatGPT 网页版来啦!响应速度超快!
- JS之判断是否为数组的方法