UE-液体倾倒Demo-开发文档
<p>[TOC]</p>
<table>
<thead>
<tr>
<th>作者</th>
<th>QFord</th>
</tr>
</thead>
<tbody>
<tr>
<td>更新日期</td>
<td>2024-8-28</td>
</tr>
</tbody>
</table>
<h1>主要需求</h1>
<p>1:虚拟实验室-化学器材液体表现Demo
1.1:基于美术提供的测试工程开发
1.2:包含基本的倾倒动画
1.3:安卓端版本
PS1:无需基于化学引擎或表现组件
PS2:需求来源于王永弟99U同步的锐锋需求。
PS3:新增了接入水流表现以及倾倒时液体柱面表现优化
1.4: 2024-8-28 液体沿着路径留下表现(1. 液体沿着杯壁留下 2:液体沿着玻璃棒流到容器中)</p>
<p>> 因相关的UE子项目立项流程中,故暂时没有单据并填写任务待命。
youxi反馈先弄这个,亦有知会锐锋了。</p>
<h1>开发工程</h1>
<p>基于UE版本的liquidDemo_240819分支开发</p>
<h1>演示视频</h1>
<p>液体倾倒DemoV0.1.0-2024-8-27 ,已99U同步。</p>
<p>> 2024-8-22 已向锐锋真机演示,新增了一个需求,详见<strong>液体表现插件2</strong></p>
<h1>已知问题</h1>
<p>液体水流碰到其他方式实现的容器的液体表面会穿透
解决方案:可统一使用液体水流所使用的插件(液体表现插件2)来实现</p>
<h1>插件</h1>
<h2>液体表现插件1</h2>
<p>插件地址
<a href="https://www.unrealengine.com/marketplace/en-US/product/chemical-workshop-42-assets">https://www.unrealengine.com/marketplace/en-US/product/chemical-workshop-42-assets</a></p>
<p>官方文档
<a href="https://www.dropbox.com/s/w10vmzkebstbdbt/Documentation.pdf?dl=0">https://www.dropbox.com/s/w10vmzkebstbdbt/Documentation.pdf?dl=0</a>
> 文档很精简,并没有提供太多有用的信息。</p>
<p>官方视频
<a href="https://www.youtube.com/watch?v=3fqPMjk7R30">https://www.youtube.com/watch?v=3fqPMjk7R30</a></p>
<p>插件资源
链接:<a href="https://im-cloud.sdp.101.com/?lang=zh-CN&sdp-app-id=b4fb92a0-af7f-49c2-b270-8f62afac1133#/sharing/7dLWvCuW">https://im-cloud.sdp.101.com/?lang=zh-CN&sdp-app-id=b4fb92a0-af7f-49c2-b270-8f62afac1133#/sharing/7dLWvCuW</a> 密码:YuKD</p>
<p>> <strong>ChemistryFlasks</strong>插件是先前我们开发同学(范丽民)技术调研过的,其经过对比多个方案后后,表示这个是表现最好的一个。</p>
<h2>液体表现插件2</h2>
<p>Contain, Pour and Spill Wine
<a href="https://www.unrealengine.com/marketplace/en-US/product/bbefd06b4c09424b8add55bed3970dba">https://www.unrealengine.com/marketplace/en-US/product/bbefd06b4c09424b8add55bed3970dba</a>
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=eac7fa093ce628274538770d7b6ac189&amp;file=file.png" alt="" /></p>
<p>> 锐锋同学2024-8-22提供的,主要有包括水流表现,而先前我们找到的那个粒子资源并不理想。
本Demo主要移植了水流表现,并进行了微调。此插件其实也支持容器内的水的表现,Demo场景主要演示了红酒倾倒和在容器内的表现。</p>
<h1>业务模块</h1>
<h2>液体表现</h2>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=28e4b9e1d546fbcdc5d606e6b7d532f5&amp;file=file.png" alt="" /></p>
<h3>液体表现适配器</h3>
<p>基于<strong>液体表现插件1</strong> 开发
<strong>ULiquidVolumeAdapter</strong> 类是一个用于管理和适配液体体积视觉表现的蓝图类。它包含了多种属性和方法,用于控制液体的外观和行为,例如液位、湍流、颜色和泡沫特性。该类提供了多个 蓝图可调用的 函数,方便我们通过蓝图来进行操作。液体表现的核心实现是插件在Shader中完成的。液体插件并未提供代码控制液体的表现,如液位的增减、液体颜色等。我们要控制相关的表现参数,可以通过操作液体的动态材质数据来实现。而ULiquidVolumeAdapter类封装了这些控制操作,便于业务层调用。</p>
<p>主要功能包括:</p>
<ul>
<li>
<p>设置液体体积网格并初始化适配器。</p>
</li>
<li>
<p>调整液位、湍流和深度衰减。</p>
</li>
<li>
<p>修改液体的主色和次色。</p>
</li>
<li>
<p>配置噪声缩放、光线步进和浑浊度。</p>
</li>
<li>
<p>控制闪烁强度和阈值。</p>
</li>
<li>
<p>管理表面湍流及其水平和垂直方向的速度。</p>
</li>
<li>设置泡沫的颜色、密度、光线步进、缩放、厚度和湍流方向。</li>
</ul>
<p>> 本Demo中主要用来控制容器内液体的液位以及颜色。
<strong>如果有更多液体相关的需求,请同步相关的开发同学</strong></p>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=8e46a13cb1ea61d5ee4ca088dbe7aa63&amp;file=file.png" alt="" /></p>
<h3>液体网格对象</h3>
<p>液体的表现适配器是通过操作液体网格对象来修改液体表现的</p>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=5cc63e0538af0e4d419442f56966ddce&amp;file=file.png" alt="" /></p>
<h3>液体表现适配器关联液体网格对象</h3>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=5952ccf25301534150eab469cda32e2a&amp;file=file.png" alt="" /></p>
<h3>创建液体表现适配器</h3>
<p>在能够控制液体表现之前,我们首先需要初始化液体表现适配器,下面是C++的实现。
而此Demo中,我们也通过蓝图来完成适配器的初始化。
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=44e95c2af9471cbcc7be91e14ca49c44&amp;file=file.png" alt="" /></p>
<h3>控制液体表现接口</h3>
<p>液体的表现关联到较多的参数,适配器中进行了良好的封装,便于我们业务层调用。
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=4dd5ddd40437335d0e1c01286bc0b98f&amp;file=file.png" alt="" /></p>
<h3>蓝图调用液体表现</h3>
<p>通过蓝图对液体适配器进行初始化,下图中我们也提供了两个简单的测试用例-液位的增加和减少。
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=9adc3ceafaf42d9619e68d7a28ca22ba&amp;file=file.png" alt="" /></p>
<h3>烧杯液体转移</h3>
<p>我们这里的液体转移考虑了流速的线性变化
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=8771dd8a43dfd71db3946d2e01365270&amp;file=file.png" alt="" /></p>
<h2>交互表现</h2>
<p>交互表现主要分为两部分,移动和旋转,分别通过<strong>InterpToMovement</strong>和<strong>RotatingMovement</strong>组件实现。
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=0165dd5cddf8ebc26ad8b8f243fc52c4&amp;file=file.png" alt="" /></p>
<p>倾倒中涉及到的旋转的停止时机控制,如果通过旋转值的Y分量来判定会遇到万向锁问题,下面是解决方案(CheckRoateStop):
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=84a77066a9447245e2d102162e58981a&amp;file=file.png" alt="" /></p>
<h2>水流表现</h2>
<h3>NS_Water_Drop_2 Niagara系统制作的水流表现</h3>
<ol>
<li>带有物理反馈,碰撞到实体会飞溅,还不满足需求
解决方案:可定制关闭飞溅效果</li>
<li>有合适的资源再替换,已预留接口,可快速接入其他水流表现。
> 非本次demo重点,不过后面锐锋有提到,又给了个新的表现接入和调试。
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=805ffcc63cdfa1b8160923d0484b6faa&amp;file=file.png" alt="" /></li>
</ol>
<h3>BP_WaterFall_Niagara 锐锋推荐的插件</h3>
<p>ContainAndSpillWine 文件夹下的Demo关卡
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=c9167d72e2eee56508a348f8e7251285&amp;file=file.png" alt="" /></p>
<p>水流表现主要是使用Bp_WaterFall_Niarara,进行了一些微调。</p>
<h4>获取液面变化速度</h4>
<p>GetFlowRate</p>
<h4>检测开始倾倒</h4>
<p>CheckBeginPull</p>
<h4>关闭水流表现</h4>
<p>DestroyWaterFall-支持渐渐变小效果</p>
<h2>Demo UI</h2>
<p>液体表现在不同光照环境下存在一些差异,因此我们提供了多个场景之间的来回切换,以便直观的对比。
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=2bcf454ca7d7b7929116e33065e44b4a&amp;file=file.png" alt="" /></p>
<h3>切换测试关卡</h3>
<p><strong>PreviewMap</strong>:简单的测试场景,主要包括两个烧杯,500ml和250ml各1个。
<strong>L_Molecule_v1</strong>:美术提供的实验室场景,除了两个烧杯,还放置了几个器材。</p>
<h3>切换液体关卡</h3>
<p><strong>demoMap</strong>:ChemistryFlasks液体表现提供的场景,包括了各种容器和相关的液体表现
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=28a11aca86c60d601839f6f12055a3bb&amp;file=file.png" alt="" /></p>
<p>> 2024-8-27更新为锐锋提供的水流插件的关卡,可作为保底方案。</p>
<h3>Demo开发文档</h3>
<p>Demo中可以直接打开本文的链接
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=52a0de138b7733541ffa0b6e35c0eb19&amp;file=file.png" alt="" /></p>
<h1>提交记录</h1>
<p><img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=ca5841b2f463841b4c9b5c2cdec99c49&amp;file=file.png" alt="" /></p>
<h1>技术总结</h1>
<h2>美术表现适配器</h2>
<p>我们虚拟实验室项目的美术表现主要可以分为下面几大类:</p>
<ol>
<li><strong>模型(Meshes)</strong>:
主要是对模型的网格进行操作,模拟各种形变表现。</li>
<li><strong>材质(Materials)</strong>:
主要是通过Shader暴露的参数,对表现进行各种控制。</li>
<li><strong>纹理(Textures)</strong>:
主要是对贴图进行更换,修改UV坐标实现纹理动画等</li>
<li><strong>动画(Animations)</strong>:
主要是对美术制作的动画表现进行控制</li>
<li><strong>粒子(Particle)</strong>:
主要是对粒子暴露的参数,对表现进行各种控制。</li>
<li><strong>音频(Audio)</strong>:
主要是处理各种音效
......</li>
</ol>
<p>&nbsp;&nbsp;&nbsp;&nbsp;在本Demo中,我们新建了一个<strong>液体表现适配器-ULiquidVolumeAdapter类</strong>,通过控制<strong>材质</strong>的Shader参数来实现容器内的液体的表现变化,这块我们是使用C++实现的,并同时为蓝图开放了接口。
&nbsp;&nbsp;&nbsp;&nbsp;此外,装有液体的容器倾倒的水流表现是通过Niagara<strong>粒子</strong>实现的,这块我们是使用<strong>蓝图类</strong>来封装控制,详见<strong>BP_WaterFall_Niagara</strong>。
&nbsp;&nbsp;&nbsp;&nbsp;总的说来,根据美术提供的资源类型,业务层可以通过<strong>表现适配器</strong>模式(程序开发人员偏爱)或者<strong>蓝图类</strong>(美术制作人员偏爱)方式来包装,以便业务层使用。
&nbsp;&nbsp;&nbsp;&nbsp;后续的表现组件开发,可以参考上述的设计。
><strong>注意:</strong> 上述的液体表现适配器并非采用设计模式中的适配器模式,因为这只是一个demo。不过在实际应用中,比如Unity版本中我们有BuildIn和URP两套资源和实现,里面的表现实现是有差异的,这时候就很适合使用适配器模式来封装,定义好材质适配器接口,用于统一不同实现的统一控制,而业务层在使用时就不用区分了。UE中我们暂未遇到这种业务场景,有需要时也可以考虑这种设计方式。</p>
<h2>全局UI</h2>
<p>&nbsp;&nbsp;&nbsp;&nbsp;在本Demo中,我们创建了负责几个关卡跳转的UI。这些UI是需要跨关卡存在的,我们也不希望反复创建。我们使用下面的第一个方案。
详见DemoGameInstance和各个关卡的关卡蓝图。
关于全局UI,主要可以通过两种方式实现:</p>
<ol>
<li>通过GameInstance创建UI,并通过各个<strong>关卡蓝图</strong>调用</li>
<li>创建Persistent Level用于创建UI,并通过Load/Unload Stream Level方式加载和卸载关卡,而不是完全切换关卡。</li>
</ol>
<h2>Niagara设置参数</h2>
<p>通过<strong>Set Niaraga Variable(数据类型)</strong>方法来设置,如下图所示:
<img src="https://www.showdoc.com.cn/server/api/attachment/visitFile?sign=5b48118313a55fa13c8a9f760f8e6d07&amp;file=file.png" alt="" /></p>
<h2>蓝图生成新对象(从C++类构建对象)</h2>
<p>使用蓝图<strong>Construct Object from Class </strong>方法</p>
<h2>生成贴花</h2>
<p>贴花是非常实用和常见的表现技术,主要可用来表现污渍、阴影、弹孔和刺青等效果,在我们虚拟实验室也有广泛的应用。
我们的demo液体流到地面或者桌面的表现中,也使用贴花技术来模拟。
主要蓝图代码是<strong>Spawn Decal at Location</strong>,可参考蓝图类<strong>BP_WaterFall_Niagara</strong>的SpawnStain方法。
此外,应用贴花,需要新建贴花材质,参考的材质是<strong>M_StainFromFlow</strong>,其中的关键点是<strong>材质域(Material Domain)</strong>设置为 <strong>Deferred Decal</strong>。</p>
<h2>Tick粒子数据</h2>
<p>Niagara粒子系统提供了蓝图<strong>Event Receive Particle Data</strong>,可用来处理粒子数据(当有数据变化时),比如粒子在碰撞时需要销毁。
实际样例可参考蓝图<strong>BP_WaterFall_Niagara</strong>的相关事件。</p>
<h2>踩坑记录</h2>
<ol>
<li>水流表现的粒子蓝图类挂载到容器口附近,如果使用 <strong>Attach Actor To Actor</strong>,将导致粒子表现不会跟随容器运动,
应该使用<strong>Attach Component To Component</strong>。</li>
</ol>
<h1>参考文档</h1>
<p>[液体模拟-技术方案](<a href="https://w.101.com/iyieuu">https://w.101.com/iyieuu</a> "液体模拟-技术方案")</p>